summaryrefslogtreecommitdiffstats
path: root/binutils-2.22/gold
diff options
context:
space:
mode:
authorBen Cheng <bccheng@google.com>2012-11-01 14:19:35 -0700
committerBen Cheng <bccheng@google.com>2012-11-01 14:27:04 -0700
commit6d5ce99288a663253fd2cde30516257f754cc776 (patch)
treed57b8b65cf7b807324908da748ba1845b8e2941a /binutils-2.22/gold
parent6b95f5ef54a29597409e24d7fe6670238d58ff04 (diff)
downloadtoolchain_binutils-6d5ce99288a663253fd2cde30516257f754cc776.zip
toolchain_binutils-6d5ce99288a663253fd2cde30516257f754cc776.tar.gz
toolchain_binutils-6d5ce99288a663253fd2cde30516257f754cc776.tar.bz2
Refresh binutils to 2.22.90.
Missing local patches will be added after. Change-Id: I7e5f7529f165a48db48a07f08b85f36c2faa8d4a
Diffstat (limited to 'binutils-2.22/gold')
-rw-r--r--binutils-2.22/gold/ChangeLog1361
-rw-r--r--binutils-2.22/gold/Makefile.am10
-rw-r--r--binutils-2.22/gold/Makefile.in42
-rw-r--r--binutils-2.22/gold/aclocal.m41
-rw-r--r--binutils-2.22/gold/archive.cc5
-rw-r--r--binutils-2.22/gold/arm.cc1402
-rw-r--r--binutils-2.22/gold/common.cc6
-rw-r--r--binutils-2.22/gold/config.in28
-rwxr-xr-xbinutils-2.22/gold/configure207
-rw-r--r--binutils-2.22/gold/configure.ac93
-rw-r--r--binutils-2.22/gold/copy-relocs.cc13
-rw-r--r--binutils-2.22/gold/descriptors.cc2
-rw-r--r--binutils-2.22/gold/dirsearch.cc25
-rw-r--r--binutils-2.22/gold/dirsearch.h7
-rw-r--r--binutils-2.22/gold/dwarf_reader.cc1485
-rw-r--r--binutils-2.22/gold/dwarf_reader.h842
-rw-r--r--binutils-2.22/gold/dynobj.cc2
-rw-r--r--binutils-2.22/gold/dynobj.h16
-rw-r--r--binutils-2.22/gold/ehframe.cc2
-rw-r--r--binutils-2.22/gold/expression.cc45
-rw-r--r--binutils-2.22/gold/fileread.cc27
-rw-r--r--binutils-2.22/gold/freebsd.h6
-rw-r--r--binutils-2.22/gold/gc.h4
-rw-r--r--binutils-2.22/gold/gdb-index.cc1236
-rw-r--r--binutils-2.22/gold/gdb-index.h213
-rw-r--r--binutils-2.22/gold/gold.cc219
-rw-r--r--binutils-2.22/gold/gold.h16
-rw-r--r--binutils-2.22/gold/i386.cc1624
-rw-r--r--binutils-2.22/gold/incremental-dump.cc8
-rw-r--r--binutils-2.22/gold/incremental.cc400
-rw-r--r--binutils-2.22/gold/incremental.h85
-rw-r--r--binutils-2.22/gold/int_encoding.cc29
-rw-r--r--binutils-2.22/gold/int_encoding.h40
-rw-r--r--binutils-2.22/gold/layout.cc737
-rw-r--r--binutils-2.22/gold/layout.h55
-rw-r--r--binutils-2.22/gold/main.cc34
-rw-r--r--binutils-2.22/gold/merge.cc51
-rw-r--r--binutils-2.22/gold/nacl.cc46
-rw-r--r--binutils-2.22/gold/nacl.h243
-rw-r--r--binutils-2.22/gold/object.cc845
-rw-r--r--binutils-2.22/gold/object.h245
-rw-r--r--binutils-2.22/gold/options.cc72
-rw-r--r--binutils-2.22/gold/options.h31
-rw-r--r--binutils-2.22/gold/output.cc260
-rw-r--r--binutils-2.22/gold/output.h417
-rw-r--r--binutils-2.22/gold/parameters.cc21
-rw-r--r--binutils-2.22/gold/parameters.h13
-rw-r--r--binutils-2.22/gold/plugin.cc51
-rw-r--r--binutils-2.22/gold/plugin.h5
-rw-r--r--binutils-2.22/gold/po/es.gmobin51373 -> 51373 bytes
-rw-r--r--binutils-2.22/gold/po/es.po6
-rw-r--r--binutils-2.22/gold/po/fi.gmobin39817 -> 50651 bytes
-rw-r--r--binutils-2.22/gold/po/fi.po1449
-rw-r--r--binutils-2.22/gold/po/it.gmobin0 -> 50879 bytes
-rw-r--r--binutils-2.22/gold/po/it.po2247
-rw-r--r--binutils-2.22/gold/powerpc.cc222
-rw-r--r--binutils-2.22/gold/readsyms.cc8
-rw-r--r--binutils-2.22/gold/reduced_debug_output.cc15
-rw-r--r--binutils-2.22/gold/reloc.h131
-rw-r--r--binutils-2.22/gold/resolve.cc21
-rw-r--r--binutils-2.22/gold/script-sections.cc47
-rw-r--r--binutils-2.22/gold/script.cc46
-rw-r--r--binutils-2.22/gold/script.h24
-rw-r--r--binutils-2.22/gold/sparc.cc1368
-rw-r--r--binutils-2.22/gold/symtab.cc115
-rw-r--r--binutils-2.22/gold/symtab.h12
-rw-r--r--binutils-2.22/gold/target-reloc.h12
-rw-r--r--binutils-2.22/gold/target-select.cc11
-rw-r--r--binutils-2.22/gold/target-select.h14
-rw-r--r--binutils-2.22/gold/target.cc4
-rw-r--r--binutils-2.22/gold/target.h39
-rw-r--r--binutils-2.22/gold/testsuite/Makefile.am122
-rw-r--r--binutils-2.22/gold/testsuite/Makefile.in211
-rw-r--r--binutils-2.22/gold/testsuite/gdb_index_test.cc138
-rwxr-xr-xbinutils-2.22/gold/testsuite/gdb_index_test_1.sh25
-rwxr-xr-xbinutils-2.22/gold/testsuite/gdb_index_test_2.sh25
-rw-r--r--binutils-2.22/gold/testsuite/gdb_index_test_3.c39
-rwxr-xr-xbinutils-2.22/gold/testsuite/gdb_index_test_3.sh49
-rwxr-xr-xbinutils-2.22/gold/testsuite/gdb_index_test_4.sh25
-rwxr-xr-xbinutils-2.22/gold/testsuite/gdb_index_test_comm.sh84
-rw-r--r--binutils-2.22/gold/testsuite/leb128_unittest.cc88
-rw-r--r--binutils-2.22/gold/testsuite/plugin_final_layout.cc41
-rwxr-xr-xbinutils-2.22/gold/testsuite/plugin_final_layout.sh60
-rw-r--r--binutils-2.22/gold/testsuite/plugin_section_order.c167
-rwxr-xr-xbinutils-2.22/gold/testsuite/plugin_test_2.sh2
-rw-r--r--binutils-2.22/gold/testsuite/relro_test.cc4
-rw-r--r--binutils-2.22/gold/testsuite/script_test_2.t2
-rw-r--r--binutils-2.22/gold/testsuite/testfile.cc14
-rw-r--r--binutils-2.22/gold/testsuite/tls_test.cc2
-rw-r--r--binutils-2.22/gold/testsuite/tls_test_c.c2
-rw-r--r--binutils-2.22/gold/timer.cc24
-rw-r--r--binutils-2.22/gold/timer.h11
-rw-r--r--binutils-2.22/gold/x86_64.cc2567
-rw-r--r--binutils-2.22/gold/yyscript.y4
94 files changed, 17465 insertions, 4659 deletions
diff --git a/binutils-2.22/gold/ChangeLog b/binutils-2.22/gold/ChangeLog
index 7f91606..e78d98b 100644
--- a/binutils-2.22/gold/ChangeLog
+++ b/binutils-2.22/gold/ChangeLog
@@ -1,3 +1,926 @@
+2012-07-18 Cary Coutant <ccoutant@google.com>
+
+ PR gold/14344
+ * configure.ac: Add check for -gpubnames support.
+ * configure: Regenerate.
+ * testsuite/Makefile.am (gdb_index_test_1): Add check for -gpubnames
+ support; force -gno-pubnames.
+ (gdb_index_test_2, gdb_index_test_3): Add check for -gpubnames
+ support.
+ (gdb_index_test_4): New test.
+ * testsuite/Makefile.in: Regenerate.
+ * testsuite/gdb_index_test_1.sh: Refactor code into common file.
+ * testsuite/gdb_index_test_2.sh: Likewise.
+ * testsuite/gdb_index_test_3.sh: Don't look for space after colon.
+ * testsuite/gdb_index_test_4.sh: New script.
+ * testsuite/gdb_index_test_comm.sh: New script with common code;
+ don't look for space after colon.
+
+2012-07-16 Sriraman Tallam <tmsriram@google.com>
+
+ * gold.cc (queue_middle_tasks): Update function order only after
+ deferred objects due to plugins are processed.
+
+2012-07-11 Ian Lance Taylor <iant@google.com>
+
+ * arm.cc (Arm_relocate_functions::abs16): Remove unused typedef.
+ (Arm_exidx_cantunwind::do_fixed_endian_write): Likewise.
+ (Target_arm::scan_reloc_for_stub): Likewise.
+ * common.cc (Symbol_table::do_allocate_commons_list): Likewise.
+ * dwarf_reader.cc (Dwarf_die::skip_attributes): Likewise.
+ * ehframe.cc (Eh_frame::do_add_ehframe_input_section): Likewise.
+ * incremental.cc (Sized_incr_dynobj::do_add_symbols): Likewise.
+ * powerpc.cc (Target_powerpc::relocate_tls): Likewise.
+
+2012-07-10 Dodji Seketeli <dodji@redhat.com>
+ Ian Lance Taylor <iant@google.com>
+
+ PR gold/14309
+ * configure.ac: Test whether std::tr1::hash<off_t> works.
+ * gold.h: Add a specialization for std::tr1::hash<off_t> if
+ needed.
+ * output.h (class Output_fill): Add virtual destructor.
+ * configure, config.in: Rebuild.
+
+2012-06-22 Roland McGrath <mcgrathr@google.com>
+
+ * layout.cc (finalize): Define __ehdr_start symbol if applicable.
+
+2012-06-12 Rafael Ávila de Espíndola <respindola@mozilla.com>
+
+ * plugin.cc (Plugin::load): Handle position independent executables.
+
+2012-06-06 Cary Coutant <ccoutant@google.com>
+
+ * layout.cc (gdb_sections): Remove ".debug_" prefixes,
+ add .debug_macro.
+ (lines_only_debug_sections): Likewise.
+ (gdb_fast_lookup_sections): New static array.
+ (is_gdb_debug_section): Rename formal parameter.
+ (is_lines_only_debug_section): Likewise.
+ (is_gdb_fast_lookup_section): New function.
+ (Layout::include_section): Check for ".zdebug_" prefix; pass
+ section name suffix to is_gdb_debug_section, et al.; check for
+ fast-lookup sections when building .gdb_index.
+ * options.h (--strip-debug-gdb): Update GDB version number.
+
+2012-06-06 Cary Coutant <ccoutant@google.com>
+
+ * configure.ac: Add check for fallocate.
+ * configure: Regenerate.
+ * config.in: Regenerate.
+
+ * options.h (class General_options): Add --mmap-output-file and
+ --posix-fallocate options.
+ * output.cc: (posix_fallocate): Remove; replace with...
+ (gold_fallocate): New function.
+ (Output_file::map_no_anonymous): Call gold_fallocate.
+ (Output_file::map): Check --mmap-output-file option.
+
+2012-06-05 Jing Yu <jingyu@google.com>
+
+ * gold.h (textdomain): Add do {} to empty while(0).
+ (bindtextdomain): Likewise.
+
+2012-06-04 Cary Coutant <ccoutant@google.com>
+
+ * dynobj.cc (Sized_dynobj::do_get_global_symbol_counts): Call
+ has_dynsym_index.
+
+2012-05-25 Sriraman Tallam <tmsriram@google.com>
+
+ * symtab.cc (Symbol_table::define_special_symbol):
+ Initialize *poldsym to prevent uninitialized variable errors.
+
+2012-05-23 Cary Coutant <ccoutant@google.com>
+
+ * layout.cc (Layout::section_name_mapping): Add rules to handle
+ exact match on .data.rel.ro.local or .data.rel.ro.
+ (Layout::output_section_name): Check for exact matches.
+
+2012-05-23 Cary Coutant <ccoutant@google.com>
+
+ * layout.cc (Layout::section_name_mapping): Match .data.rel.ro.*
+ more carefully.
+
+2012-05-22 Cary Coutant <ccoutant@google.com>
+
+ * symtab.cc (Symbol::should_add_dynsym_entry): Check for relocatable
+ object before exporting symbol.
+
+2012-05-21 H.J. Lu <hongjiu.lu@intel.com>
+
+ * testsuite/tls_test.cc: Include "config.h" first.
+ * testsuite/tls_test_c.c: Likewise.
+
+2012-05-17 Daniel Richard G. <skunk@iskunk.org>
+ Nick Clifton <nickc@redhat.com>
+
+ PR 14072
+ * configure.in: Add check that sysdep.h has been included before
+ any system header files.
+ * configure: Regenerate.
+ * config.in: Regenerate.
+
+2012-05-14 Cary Coutant <ccoutant@google.com>
+
+ * layout.cc (Layout::make_output_section): Mark .tdata section
+ as RELRO.
+ * testsuite/relro_test.cc: Add a TLS variable.
+
+2012-05-10 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR gold/14091
+ * x86_64.cc (Target_x86_64::Scan::local): For x32, generate
+ R_X86_64_RELATIVE64 instead of R_X86_64_RELATIVE in case of
+ R_X86_64_64.
+
+2012-05-08 Cary Coutant <ccoutant@google.com>
+
+ * layout.cc (gdb_sections): Update GDB version, add .debug_addr.
+ (lines_only_debug_sections): Likewise.
+
+2012-05-02 Roland McGrath <mcgrathr@google.com>
+
+ * nacl.cc: New file.
+ * nacl.h: New file.
+ * Makefile.am (CCFILES, HFILES): Add them.
+ * Makefile.in: Regenerate.
+ * i386.cc (Output_data_plt_i386_nacl): New class.
+ (Output_data_plt_i386_nacl_exec): New class.
+ (Output_data_plt_i386_nacl_dyn): New class.
+ (Target_i386_nacl): New class.
+ (Target_selector_i386_nacl): New class.
+ (target_selector_i386): Use it instead of Target_selector_i386.
+ * x86_64.cc (Output_data_plt_x86_64_nacl): New class.
+ (Target_x86_64_nacl): New class.
+ (Target_selector_x86_64_nacl): New class.
+ (target_selector_x86_64, target_selector_x32): Use it instead of
+ Target_selector_x86_64.
+ * arm.cc (Output_data_plt_arm_nacl): New class.
+ (Target_arm_nacl): New class.
+ (Target_selector_arm_nacl): New class.
+ (target_selector_arm, target_selector_armbe): Use it instead of
+ Target_selector_arm.
+
+ * target-select.cc (select_target): Take new Input_file* and off_t
+ arguments, pass them on to recognize method of selector.
+ * object.cc (make_elf_sized_object): Update caller.
+ * parameters.cc (parameters_force_valid_target): Likewise.
+ * incremental.cc (make_sized_incremental_binary): Likewise.
+ * target-select.h: Update decl.
+ (Target_selector::recognize): Take new Input_file* argument,
+ pass it on to do_recognize.
+ (Target_selector::do_recognize): Take new Input_file* argument.
+ * freebsd.h (Target_selector_freebsd::do_recognize): Likewise.
+ * powerpc.cc (Target_selector_powerpc::do_recognize): Likewise.
+ * sparc.cc (Target_selector_sparc::do_recognize): Likewise.
+ * testsuite/testfile.cc (Target_selector::do_recognize): Likewise.
+
+ * target.h (Target::Target_info): New members isolate_execinstr
+ and rosegment_gap.
+ (Target::isolate_execinstr, Target::rosegment_gap): New methods.
+ * arm.cc (Target_arm::arm_info): Update initializer.
+ * i386.cc (Target_i386::i386_info): Likewise.
+ * powerpc.cc (Target_powerpc::powerpc_info): Likewise.
+ * sparc.cc (Target_sparc::sparc_info): Likewise.
+ * x86_64.cc (Target_x86_64::x86_64_info): Likewise.
+ * testsuite/testfile.cc (Target_test::test_target_info): Likewise.
+ * layout.cc (Layout::attach_allocated_section_to_segment):
+ Take new const Target* argument. If target->isolate_execinstr(), act
+ like --rosegment.
+ (Layout::find_first_load_seg): Take new const Target* argument;
+ if target->isolate_execinstr(), reject PF_X segments.
+ (Layout::relaxation_loop_body): Update caller.
+ (Layout::set_segment_offsets): If target->isolate_execinstr(),
+ reset file offset to zero when we hit LOAD_SEG, and then do a second
+ loop over the segments before LOAD_SEG to reassign offsets after
+ addresses have been determined. Handle target->rosegment_gap().
+ (Layout::attach_section_to_segment): Take new const Target* argument;
+ pass it to attach_allocated_section_to_segment.
+ (Layout::make_output_section): Update caller.
+ (Layout::attach_sections_to_segments): Take new const Target* argument;
+ pass it to attach_section_to_segment.
+ * gold.cc (queue_middle_tasks): Update caller.
+ * layout.h (Layout): Update method decls with new arguments.
+
+ * arm.cc (Target_arm::Target_arm): Take optional argument for the
+ Target_info pointer to use.
+ (Target_arm::do_make_data_plt): New virtual method.
+ (Target_arm::make_data_plt): New method that calls it.
+ (Target_arm::make_plt_entry): Use it.
+ (Output_data_plt_arm::Output_data_plt_arm): Take additional argument
+ for the section alignment.
+ (Output_data_plt_arm::do_first_plt_entry_offset): New abstract virtual
+ method.
+ (Output_data_plt_arm::first_plt_entry_offset): Call it.
+ (Output_data_plt_arm::do_get_plt_entry_size): New abstract virtual
+ method.
+ (Output_data_plt_arm::get_plt_entry_size): Call it.
+ (Output_data_plt_arm::do_fill_plt_entry): New abstract virtual method.
+ (Output_data_plt_arm::fill_plt_entry): New method that calls it.
+ (Output_data_plt_arm::do_fill_first_plt_entry): New abstract virtual
+ method.
+ (Output_data_plt_arm::fill_first_plt_entry): New method that calls it.
+ (Output_data_plt_arm::set_final_data_size): Use get_plt_entry_size
+ method instead of sizeof(plt_entry).
+ (Output_data_plt_arm::add_entry): Likewise.
+ Use first_plt_entry_offset method instead of sizeof(first_plt_entry).
+ (Target_arm::first_plt_entry_offset): Call method on this->plt_ rather
+ than static method.
+ (Target_arm::plt_entry_size): Likewise.
+ (Output_data_plt_arm::first_plt_entry, Output_data_plt_arm::plt_entry):
+ Move to ...
+ (Output_data_plt_arm_standard): ... here, new class.
+ (Output_data_plt_arm::do_write): Move guts of PLT filling to...
+ (Output_data_plt_arm_standard::do_fill_first_plt_entry): ... here ...
+ (Output_data_plt_arm_standard::do_fill_plt_entry): ... and here.
+
+ * x86_64.cc (Output_data_plt_x86_64::Output_data_plt_x86_64):
+ Take additional argument for the PLT entry size.
+ (Output_data_plt_x86_64::get_tlsdesc_plt_offset):
+ Use get_plt_entry_size method rather than plt_entry_size variable.
+ (Output_data_plt_x86_64::reserve_slot): Likewise.
+ (Output_data_plt_x86_64::do_adjust_output_section): Likewise.
+ (Output_data_plt_x86_64::add_entry): Likewise.
+ (Output_data_plt_x86_64::add_local_ifunc_entry): Likewise.
+ (Output_data_plt_x86_64::address_for_global): Likewise.
+ (Output_data_plt_x86_64::address_for_local): Likewise.
+ (Output_data_plt_x86_64::set_final_data_size): Likewise.
+ (Output_data_plt_x86_64::first_plt_entry_offset): Likewise.
+ Make method non-static.
+ (Output_data_plt_x86_64::do_get_plt_entry_size): New abstract virtual
+ method.
+ (Output_data_plt_x86_64::get_plt_entry_size): Just call that.
+ (Output_data_plt_x86_64::do_add_eh_frame): New abstract virtual method.
+ (Output_data_plt_x86_64::add_eh_frame): New method to call it.
+ (Output_data_plt_x86_64::do_fill_first_plt_entry): New abstract
+ virtual method.
+ (Output_data_plt_x86_64::fill_first_plt_entry): New method to call it.
+ (Output_data_plt_x86_64::do_fill_plt_entry): New abstract
+ virtual method.
+ (Output_data_plt_x86_64::fill_plt_entry): New method to call it.
+ (Output_data_plt_x86_64::do_fill_tlsdesc_entry): New abstract
+ virtual method.
+ (Output_data_plt_x86_64::fill_tlsdesc_entry): New method to call it.
+ (Output_data_plt_x86_64::plt_entry_size)
+ (Output_data_plt_x86_64::first_plt_entry)
+ (Output_data_plt_x86_64::plt_entry)
+ (Output_data_plt_x86_64::tlsdesc_plt_entry)
+ (Output_data_plt_x86_64::plt_eh_frame_fde_size)
+ (Output_data_plt_x86_64::plt_eh_frame_fde): Move to ...
+ (Output_data_plt_x86_64_standard): ... here, new class.
+ (Target_x86_64::Target_x86_64): Take optional argument for the
+ Target_info pointer to use.
+ (Target_x86_64::do_make_data_plt): New virtual method.
+ (Target_x86_64::make_data_plt): New method to call it.
+ (Target_x86_64::init_got_plt_for_update): Use that.
+ Call this->plt_->add_eh_frame method here.
+ (Output_data_plt_x86_64::init): Don't do add_eh_frame_for_plt here.
+ (Target_x86_64::first_plt_entry_offset): Call method on this->plt_
+ rather than static method.
+ (Target_x86_64::plt_entry_size): Likewise.
+ (Output_data_plt_x86_64::do_write): Use get_plt_entry_size method
+ rather than plt_entry_size variable. Move guts of PLT filling to...
+ (Output_data_plt_x86_64_standard::do_fill_first_plt_entry): ... here ...
+ (Output_data_plt_x86_64_standard::do_fill_plt_entry): ... and here ...
+ (Output_data_plt_x86_64_standard::do_fill_tlsdesc_entry): ... and here.
+
+ * i386.cc (Output_data_plt_i386::Output_data_plt_i386): Take
+ additional argument for the section alignment.
+ Don't do add_eh_frame_for_plt here.
+ (Output_data_plt_i386::first_plt_entry_offset): Make the method
+ non-static. Use get_plt_entry_size method rather than plt_entry_size
+ variable.
+ (Output_data_plt_i386::do_get_plt_entry_size): New abstract virtual
+ method.
+ (Output_data_plt_i386::get_plt_entry_size): Call it.
+ (Output_data_plt_i386::do_add_eh_frame): New abstract virtual method.
+ (Output_data_plt_i386::add_eh_frame): New method to call it.
+ (Output_data_plt_i386::do_fill_first_plt_entry): New abstract virtual
+ method.
+ (Output_data_plt_i386::fill_first_plt_entry): New method to call it.
+ (Output_data_plt_i386::do_fill_plt_entry): New abstract virtual
+ method.
+ (Output_data_plt_i386::fill_plt_entry): New method to call it.
+ (Output_data_plt_i386::set_final_data_size): Use get_plt_entry_size
+ method instead of plt_entry_size.
+ (Output_data_plt_i386::plt_entry_size)
+ (Output_data_plt_i386::plt_eh_frame_fde_size)
+ (Output_data_plt_i386::plt_eh_frame_fde): Move to ...
+ (Output_data_plt_i386_standard): ... here, new class.
+ (Output_data_plt_i386_exec): New class.
+ (Output_data_plt_i386::exec_first_plt_entry): Move to ...
+ (Output_data_plt_i386_exec::first_plt_entry): ... here.
+ (Output_data_plt_i386::exec_plt_entry): Move to ...
+ (Output_data_plt_i386_exec::plt_entry): ... here.
+ (Output_data_plt_i386_dyn): New class.
+ (Output_data_plt_i386::first_plt_entry): Move to ...
+ (Output_data_plt_i386_dyn::first_plt_entry): ... here.
+ (Output_data_plt_i386::dyn_plt_entry): Move to ...
+ (Output_data_plt_i386_dyn::plt_entry): ... here.
+ (Target_i386::Target_i386): Take optional argument for the Target_info
+ pointer to use.
+ (Target_i386::do_make_data_plt): New virtual method.
+ (Target_i386::make_data_plt): New method to call it.
+ (Target_i386::make_plt_section): Use that.
+ Call this->plt_->add_eh_frame method here.
+ (Output_data_plt_i386::add_entry): Use get_plt_entry_size method
+ rather than plt_entry_size variable.
+ (Output_data_plt_i386::add_local_ifunc_entry): Likewise.
+ (Output_data_plt_i386::address_for_local): Likewise.
+ (Output_data_plt_i386::do_write): Likewise.
+ Move guts of PLT filling to...
+ (Output_data_plt_i386_exec::do_fill_first_plt_entry): ... here ...
+ (Output_data_plt_i386_exec::do_fill_plt_entry): ... and here ...
+ (Output_data_plt_i386_dyn::do_fill_first_plt_entry): ... and here ...
+ (Output_data_plt_i386_dyn::do_fill_plt_entry): ... and here.
+
+2012-05-01 Cary Coutant <ccoutant@google.com>
+
+ * dwarf_reader.cc (Dwarf_die::read_attributes)
+ (Dwarf_die::skip_attributes, Dwarf_die::int_attribute)
+ (Dwarf_die::uint_attribute): Remove DW_FORM_null.
+ * reduced_debug_output.cc
+ (Output_reduced_debug_info_section::get_die_end): Remove
+ DW_FORM_GNU_ref_index. Add default case.
+
+2012-04-26 Mark Wielaard <mjw@redhat.com>
+
+ * dwarf_reader.cc (Dwarf_die::address_attribute): New function.
+ * dwarf_reader.h (Dwarf_die::address_attribute): Likewise.
+ * gdb-index.cc (Gdb_index_info_reader::record_cu_ranges): Handle
+ DW_AT_high_pc as offset from DW_AT_low_pc.
+
+ * testsuite/Makefile.am (gdb_index_test_3.sh): New test case.
+ * testsuite/Makefile.in: Regenerate.
+ * testsuite/gdb_index_test_3.c: New test source file.
+ * testsuite/gdb_index_test_3.sh: New test source file.
+
+2012-04-25 Ian Lance Taylor <iant@google.com>
+
+ * arm.cc (Target_arm::do_is_defined_by_abi): Make sym a const
+ pointer.
+ (Stub_addend_reader::operator()): Declare Arm_relocate_functions
+ as a class, not a struct.
+ (Target_arm::scan_span_for_cortex_a8_erratum): Likewise.
+ (Target_arm::apply_cortex_a8_workaround): Likewise.
+ * gc.h: Declare Reloc_types as a struct, not a class.
+ * object.h: Declare Symbols_data as a struct.
+ * reloc.h: Declare Read_relocs_data as a struct.
+ * target.h: Declare Relocate_info as a struct.
+
+2012-04-24 David S. Miller <davem@davemloft.net>
+
+ * sparc.cc (Target_sparc::Relocate::relax_call): New function.
+ (Target_sparc::Relocate::relocate): Call it for R_SPARC_WDISP30
+ and R_SPARC_WPLT30.
+
+2012-04-24 Cary Coutant <ccoutant@google.com>
+
+ * incremental-dump.cc (find_input_containing_global): Replace
+ magic number with symbolic constant.
+ (dump_incremental_inputs): Update version number.
+ * incremental.cc (Output_section_incremental_inputs): Update version
+ number; import symbolic constants from Incremental_inputs_reader.
+ (Incremental_inputs::create_data_sections): Align relocations
+ section correctly for 64-bit targets.
+ (Output_section_incremental_inputs::set_final_data_size): Use symbolic
+ constants; add padding.
+ (Output_section_incremental_inputs::write_header): Add assert for
+ header_size.
+ (Output_section_incremental_inputs::write_input_files): Add assert
+ for input_entry_size.
+ (Output_section_incremental_inputs::write_info_blocks): Add padding;
+ add assert for object_info_size, input_section_entry_size,
+ global_sym_entry_size.
+ * incremental.h (Incremental_inputs_reader): Add symbolic constants
+ for data structure sizes; use them.
+ (Incremental_input_entry_reader): Import symbolic constants from
+ Incremental_inputs_reader; use them.
+
+2012-04-23 David S. Miller <davem@davemloft.net>
+
+ * sparc.cc (class Target_sparc): Add elf_machine_, elf_flags_,
+ and elf_flags_set_.
+ (Target_sparc::Target_sparc): Initialize new fields.
+ (Target_sparc::do_make_elf_object): New function.
+ (Target_sparc::do_adjust_elf_header): New function.
+
+2012-04-23 Cary Coutant <ccoutant@google.com>
+
+ * gdb-index.cc (Gdb_index::do_write): Use Swap_aligned32 for writing
+ CU range table of gdb index.
+
+2012-04-20 David S. Miller <davem@davemloft.net>
+
+ * target.cc (Sized_target::do_adjust_elf_header): Use big_endian
+ instead of false.
+
+2012-04-16 David S. Miller <davem@davemloft.net>
+
+ * sparc.cc (Target_sparc::got_address): New function.
+ (Sparc_relocate_functions::gdop_hix22): New function.
+ (Sparc_relocate_functions::gdop_lox10): New function.
+ (Target_sparc::Scan::local): Do not emit a GOT entry for GOTDATA
+ relocs.
+ (Target_sparc::Scan::local): Likewise if the global symbol is not
+ preemptible and is not IFUNC.
+ (Target_sparc::Relocate::relocate): Perform GOTDATA code
+ transformations for local and non-preemptible non-IFUNC global
+ symbols.
+
+ * gdb-index.cc (Gdb_index::do_write): Use Swap_unaligned when
+ writing out 64-bit part of ranges.
+
+ * Makefile.am: Build IFUNC tests with -fPIC and -fPIE instead of
+ -fpic and -fpie respectively.
+ * Makefile.in: Regenerate.
+
+ * sparc.cc (class Target_sparc): Add rela_ifunc_.
+ (Target_sparc::Target_sparc): Initialize new field.
+ (Target_sparc::do_plt_section_for_global): New function.
+ (Target_sparc::do_plt_section_for_local): New function.
+ (Target_sparc::reloc_needs_plt_for_ifunc): New function.
+ (Target_sparc::make_plt_section): New function, broken out of
+ make_plt_entry. Use ORDER_NON_RELRO_FIRST for ".plt".
+ (Target_sparc::make_plt_entry): Call make_plt_section.
+ (Target_sparc::make_local_ifunc_plt_entry): New function.
+ (Target_sparc::rela_ifunc_section): New function.
+ (Target_sparc::plt_section): Remove const.
+ (Output_data_plt_sparc): Update declarations. Define Global_ifunc
+ and Local_ifunc types. Add global_ifuncs_, local_ifuncs_, ifunc_rel_,
+ and ifunc_count_ fields.
+ (Output_data_plt_sparc::Output_data_plt_sparc): Initialize new fields.
+ (Output_data_plt_sparc::add_entry): Handle IFUNC symbols.
+ (Output_data_plt_sparc::add_local_ifunc_entry): New function.
+ (Output_data_plt_sparc::rela_ifunc): New function.
+ (Output_data_plt_sparc::emit_pending_ifunc_relocs): New function.
+ (Output_data_plt_sparc::has_ifunc_section): New function.
+ (Output_data_plt_sparc::entry_count): Include ifunc_count_.
+ (Output_data_plt_sparc::address_for_global): New function.
+ (Output_data_plt_sparc::address_for_local): New function.
+ (Output_data_plt_sparc::plt_index_to_offset): New function.
+ (Output_data_plt_sparc::set_final_data_size): Use plt_index_to_offset
+ and entry_count.
+ (Output_data_plt_sparc::do_write): Use first_plt_entry_offset and
+ entry_count.
+ (Target_sparc::Scan::get_reference_flags): Add R_SPARC_IRELATIVE and
+ R_SPARC_JMP_IREL to switch.
+ (Target_sparc::Scan::check_non_pic): Likewise.
+ (Target_sparc::Scan::local): Handle IFUNC symbols.
+ (Target_sparc::Scan::local): Likewise.
+ (Target_sparc::Relocate::relocate): Likewise, use plt_address_for_global
+ and plt_address_for_local.
+ (Target_sparc::do_finalize_sections): Call emit_pending_ifunc_relocs.
+ Define __rel_iplt_start and __rel_iplt_end if doing a static link.
+
+ * output.h (Output_reloc): Allow use_plt_offset for global relocs too.
+ (class Output_data_reloc): Adjust calls to Output_reloc_type.
+ (Output_data_reloc::add_global_relative): (RELA only) Add use_plt_offset.
+ * output.cc (Output_reloc::Output_reloc): Add use_plt_offset flag for
+ global relocs too.
+ (Output_reloc::symbol_value): Respect use_plt_offset_ for global symbols.
+ * powerpc.cc (Target_powerpc::Scan::global): Adjust add_global_relative
+ calls.
+ * sparc.cc (Target_sparc::Scan::global): Likewise.
+ * x86_64.cc (Target_x86_64::Scan::global): Likewise.
+
+2012-04-16 Cary Coutant <ccoutant@google.com>
+
+ * archive.cc (Library_base::should_include_member): Check for
+ --export-dynamic-symbol.
+ * options.h (class General_options): Add --export-dynamic-symbol.
+ * symtab.cc (Symbol::should_add_dynsym_entry): Check for
+ --export-dynamic-symbol.
+ (Symbol_table::gc_mark_undef_symbols): Likewise.
+ (Symbol_table::do_add_undefined_symbols_from_command_line): Likewise.
+
+2012-04-12 David S. Miller <davem@davemloft.net>
+
+ * sparc.cc (Reloc::wdisp10): New relocation method.
+ (Reloc::h34): Likewise.
+ (Target_sparc::Scan::check_non_pic): Handle R_SPARC_H34.
+ (Target_sparc::Scan::get_reference_flags): Handle R_SPARC_H34 and
+ R_SPARC_WDISP10.
+ (Target_sparc::Scan::local): Likewise.
+ (Target_sparc::Scan::global): Likewise.
+ (Target_sparc::Relocate::relocate): Likewise.
+
+2012-04-09 Cary Coutant <ccoutant@google.com>
+
+ * gdb-index.cc (Gdb_index_info_reader::record_cu_ranges): Allow
+ low_pc == 0.
+
+2012-04-06 Ian Lance Taylor <iant@google.com>
+
+ * timer.cc: #include <unistd.h>.
+
+2012-04-06 Roland McGrath <mcgrathr@google.com>
+
+ * configure.in (AC_CHECK_HEADERS): Add locale.h.
+ * config.in: Regenerate.
+ * configure: Regenerate.
+
+2012-04-05 Nick Clifton <nickc@redhat.com>
+
+ * configure.ac (AC_CHECK_FUNCS): Add setlocale.
+ (AM_LC_MESSAGES): Add.
+ * aclocal.m4: Regenerate.
+ * config.in: Regenerate.
+ * configure: Regenerate.
+
+2012-03-21 Cary Coutant <ccoutant@google.com>
+
+ * Makefile.am: Add gdb-index.cc, gdb-index.h.
+ * Makefile.in: Regenerate.
+ * dwarf_reader.cc (Sized_elf_reloc_mapper::do_initialize): New function.
+ (Sized_elf_reloc_mapper::symbol_section): New function.
+ (Sized_elf_reloc_mapper::do_get_reloc_target): New function.
+ (make_elf_reloc_mapper): New function.
+ (Dwarf_abbrev_table::clear_abbrev_codes): New function.
+ (Dwarf_abbrev_table::do_read_abbrevs): New function.
+ (Dwarf_abbrev_table::do_get_abbrev): New function.
+ (Dwarf_ranges_table::read_ranges_table): New function.
+ (Dwarf_ranges_table::read_range_list): New function.
+ (Dwarf_pubnames_table::read_section): New function.
+ (Dwarf_pubnames_table::read_header): New function.
+ (Dwarf_pubnames_table::next_name): New function.
+ (Dwarf_die::Dwarf_die): New function.
+ (Dwarf_die::read_attributes): New function.
+ (Dwarf_die::skip_attributes): New function.
+ (Dwarf_die::set_name): New function.
+ (Dwarf_die::set_linkage_name): New function.
+ (Dwarf_die::attribute): New function.
+ (Dwarf_die::string_attribute): New function.
+ (Dwarf_die::int_attribute): New function.
+ (Dwarf_die::uint_attribute): New function.
+ (Dwarf_die::ref_attribute): New function.
+ (Dwarf_die::child_offset): New function.
+ (Dwarf_die::sibling_offset): New function.
+ (Dwarf_info_reader::check_buffer): New function.
+ (Dwarf_info_reader::parse): New function.
+ (Dwarf_info_reader::do_parse): New function.
+ (Dwarf_info_reader::do_read_string_table): New function.
+ (Dwarf_info_reader::lookup_reloc): New function.
+ (Dwarf_info_reader::get_string): New function.
+ (Dwarf_info_reader::visit_compilation_unit): New function.
+ (Dwarf_info_reader::visit_type_unit): New function.
+ (Sized_dwarf_line_info::Sized_dwarf_line_info): Use
+ Sized_elf_reloc_mapper.
+ (Sized_dwarf_line_info::symbol_section): Remove function.
+ (Sized_dwarf_line_info::read_relocs): Use Sized_elf_reloc_mapper.
+ (Sized_dwarf_line_info::read_line_mappings): Remove object
+ parameter, adjust callers.
+ (Sized_dwarf_line_info::format_file_lineno): Fix type of cast.
+ * dwarf_reader.h: Include <sys/types.h>.
+ (class Track_relocs): Remove forward declaration.
+ (class Elf_reloc_mapper): New class.
+ (class Sized_elf_reloc_mapper): New class.
+ (class Dwarf_abbrev_table): New class.
+ (class Dwarf_range_list): New class.
+ (class Dwarf_ranges_table): New class.
+ (class Dwarf_pubnames_table): New class.
+ (class Dwarf_die): New class.
+ (class Dwarf_info_reader): New class.
+ (Sized_dwarf_line_info::read_line_mappings): Remove object parameter.
+ (Sized_dwarf_line_info::symbol_section): Remove member function.
+ * dynobj.h (Sized_dynobj::do_section_contents): Refactor code from
+ base class.
+ * gdb-index.cc: New source file.
+ * gdb-index.h: New source file.
+ * incremental.cc (Sized_relobj_incr::do_layout): Track .debug_info
+ and .debug_types sections, call Layout::add_to_gdb_index.
+ (Sized_relobj_incr::do_section_name): Implement.
+ (Sized_relobj_incr::do_section_contents): Adjust parameter list and
+ return type; Implement.
+ (Sized_incr_dynobj::do_section_contents): Adjust parameter list and
+ return type.
+ * incremental.h (Sized_relobj_incr::do_section_contents): Adjust
+ parameter list and return type.
+ (Sized_incr_dynobj::do_section_contents): Likewise.
+ * layout.cc: Include gdb-index.h.
+ (Layout::Layout): Initialize gdb_index_data_.
+ (Layout::init_fixed_output_section): Check for .gdb_index section.
+ (Layout::add_to_gdb_index): New function. Instantiate.
+ * layout.h: Add forward declaration for class Gdb_index.
+ (Layout::add_to_gdb_index): New member function.
+ (Layout::gdb_index_data_): New data member.
+ * main.cc: Include gdb-index.h.
+ (main): Print statistics for gdb index.
+ * object.cc (Object::section_contents): Move code into
+ do_section_contents.
+ (need_decompressed_section): Check for sections needed when building
+ gdb index.
+ (build_compressed_section_map): Likewise.
+ (Sized_relobj_file::do_read_symbols): Need local symbols when building
+ gdb index.
+ (Sized_relobj_file::do_layout): Track .debug_info and .debug_types
+ sections; call Layout::add_to_gdb_index.
+ (Sized_relobj_file::do_decompressed_section_contents): Call
+ do_section_contents directly.
+ * object.h (Object::do_section_contents): Adjust parameter list and
+ return type.
+ (Object::do_decompressed_section_contents): Call do_section_contents
+ directly.
+ (Sized_relobj_file::do_section_contents): Adjust parameter list and
+ return type.
+ * options.h (class General_options): Add --gdb-index option.
+ * plugin.cc (Sized_pluginobj::do_section_contents): Adjust parameter
+ list and return type.
+ * plugin.h (Sized_pluginobj::do_section_contents): Likewise.
+ * reloc.h (Track_relocs::checkpoint): New function.
+ (Track_relocs::reset): New function.
+
+ * testsuite/Makefile.am (gdb_index_test_1.sh, gdb_index_test_2.sh):
+ New test cases.
+ * testsuite/Makefile.in: Regenerate.
+ * testsuite/gdb_index_test.cc: New test source file.
+ * testsuite/gdb_index_test_1.sh: New test source file.
+ * testsuite/gdb_index_test_2.sh: New test source file.
+
+2012-03-19 Doug Kwan <dougkwan@google.com>
+
+ * arm.cc (Target_arm::do_define_standard_symbols): New method.
+ (Target_arm::do_finalize_sections): Remove code which defines
+ __exidx_start and __exidx_end. Make symbol table parameter
+ anonymous as it is not used.
+ * gold.cc (queue_middle_tasks): Call target hook to define any
+ target-specific symbols.
+ * target.h (Target::define_standard_symbols): New method.
+ (Target::do_define_standard_symbols): Same.
+ * testsuite/Makefile.am (arm_exidx_test): Dump relocations also.
+ * testsuite/Makefile.in: Regenerate.
+ * testsuite/arm_exidx.s: Generate data relocations for __exidx_start
+ and __exidx_end.
+ * testsuite/arm_exidx_test.sh: Check that no unused dynamic
+ relocations are generated for __exidx_start and __exidx_end.
+
+2012-03-16 Doug Kwan <dougkwan@google.com>
+
+ * testsuite/Makefile.am: Disable test initpri3b.
+ * testsuite/Makefile.in: Regenerate.
+
+2012-03-15 Doug Kwan <dougkwan@google.com>
+
+ * arm.cc (Target_arm::got_section): Make .got section read-only
+ if -z now is given.
+
+2012-03-15 Ian Lance Taylor <iant@google.com>
+
+ PR gold/13850
+ * layout.cc (Layout::make_output_section): Correctly mark
+ SHT_INIT_ARRAY, et. al., as relro.
+
+2012-03-14 Doug Kwan <dougkwan@google.com>
+
+ * gold/arm.cc (Target_arm::Scan::global): Generate R_ARM_GLOB_DAT
+ dynamic relocations for protected symbols in shared objects.
+
+2012-03-13 Ian Lance Taylor <iant@google.com>
+
+ * resolve.cc (Symbol_table::resolve): When merging common symbols,
+ keep the larger alignment.
+
+2012-03-12 Cary Coutant <ccoutant@google.com>
+
+ * dwarf_reader.cc (Sized_dwarf_line_info::process_one_opcode): Fix
+ handling of DW_LNE_define_file.
+
+2012-03-12 Cary Coutant <ccoutant@google.com>
+
+ * reduced_debug_output.cc
+ (Output_reduced_debug_info_section::get_die_end): Add new FORM
+ codes to switch.
+
+2012-02-29 Cary Coutant <ccoutant@google.com>
+
+ * object.cc (need_decompressed_section): Add #ifdef ENABLE_THREADS.
+
+2012-02-29 Cary Coutant <ccoutant@google.com>
+
+ * dwarf_reader.cc (Sized_dwarf_line_info::Sized_dwarf_line_info):
+ Call Object::decompressed_section_contents.
+ * dwarf_reader.h (Sized_dwarf_line_info::~Sized_dwarf_line_info):
+ New dtor.
+ (Sized_dwarf_line_info::buffer_start_): New data member.
+ * merge.cc (Output_merge_data::do_add_input_section): Call
+ Object::decompressed_section_contents.
+ (Output_merge_string::do_add_input_section): Likewise.
+ * object.cc (need_decompressed_section): New function.
+ (build_compressed_section_map): Decompress sections needed later.
+ (Sized_relobj_file::do_decompressed_section_contents): New function.
+ (Sized_relobj_file::do_discard_decompressed_sections): New function.
+ * object.h (Object::decompressed_section_contents): New function.
+ (Object::discard_decompressed_sections): New function.
+ (Object::do_decompressed_section_contents): New function.
+ (Object::do_discard_decompressed_sections): New function.
+ (Compressed_section_info): New type.
+ (Compressed_section_map): Include decompressed section contents.
+ (Sized_relobj_file::do_decompressed_section_contents): New function.
+ (Sized_relobj_file::do_discard_decompressed_sections): New function.
+
+2012-02-16 Cary Coutant <ccoutant@google.com>
+
+ * testsuite/Makefile.am (initpri2): Add --ctors-in-init-array option.
+ * testsuite/Makefile.in: Regenerate.
+
+2012-02-14 Cary Coutant <ccoutant@google.com>
+
+ * options.cc (General_options::finalize): Disallow -pie and -static.
+
+2012-02-03 Doug Kwan <dougkwan@google.com>
+
+ * arm.cc (Arm_relocate_functions::abs8,
+ Arm_relocate_functions::abs16): Use
+ Bits::has_signed_unsigned_overflow32.
+ (Arm_relocate_functions::thm_abs8): Correct range of
+ overflow check.
+ * reloc.h (Bits class): Change minimum number of bits from 0 to 1
+ in assertions.
+
+2012-02-02 Doug Kwan <dougkwan@google.com>
+
+ * arm.cc (Reloc_stub::stub_type_for_reloc): Use PIC stubs in all
+ position independent outputs, not just shared objects.
+
+2012-01-30 H.J. Lu <hongjiu.lu@intel.com>
+
+ * configure.ac: Check if -fpic -mtls-dialect=gnu2 works.
+ * configure: Regenerated.
+
+2012-01-27 Ian Lance Taylor <iant@google.com>
+
+ * reloc.h (Bits): New class with static functions, copied from
+ namespace utils in arm.cc.
+ * arm.cc (namespace utils): Remove. Rewrite all uses to use Bits
+ instead.
+
+2012-01-27 H.J. Lu <hongjiu.lu@intel.com>
+
+ * incremental.cc (write_info_blocks): Correct relocation offset.
+
+2012-01-27 H.J. Lu <hongjiu.lu@intel.com>
+
+ * x86_64.cc (Relocate::tls_gd_to_ie): Support x32.
+ (Relocate::tls_gd_to_le): Likewise.
+
+2012-01-27 H.J. Lu <hongjiu.lu@intel.com>
+
+ * x86_64.cc (Scan::global): Support x32 IFUNC function pointer.
+
+2012-01-27 H.J. Lu <hongjiu.lu@intel.com>
+
+ * configure.ac: Check if -mcmodel=medium works.
+ * configure: Regenerated.
+
+2012-01-24 Cary Coutant <ccoutant@google.com>
+
+ * int_encoding.cc (read_unsigned_LEB_128): Replaced with inline
+ definition and ...
+ (read_unsigned_LEB_128_x): ... this new function.
+ (read_signed_LEB_128): Replaced with inline definition and ...
+ (read_signed_LEB_128_x): ... this new function.
+ * int_encoding.h (read_unsigned_LEB_128_x): New function.
+ (read_unsigned_LEB_128): Add inline definition.
+ (read_signed_LEB_128_x): New function.
+ (read_signed_LEB_128): Add inline definition.
+ * testsuite/Makefile.am (leb128_unittest): New unit test.
+ * testsuite/Makefile.in: Regenerate.
+ * testsuite/leb128_unittest.cc: New unit test.
+
+2012-01-23 Ian Lance Taylor <iant@google.com>
+
+ PR gold/13617
+ * i386.cc (Target_i386::do_code_fill): When using a jmp
+ instruction, pad with nop instructions.
+ * x86_64.cc (Target_x86_64::do_code_fill): Likewise.
+
+2012-01-22 H.J. Lu <hongjiu.lu@intel.com>
+
+ * x86_64.cc (gc_process_relocs): Add typename on types used in
+ template.
+ (scan_relocs): Likewise.
+ (relocate_section): Likewise.
+ (apply_relocation): Likewise.
+
+2012-01-10 H.J. Lu <hongjiu.lu@intel.com>
+
+ * x86_64.cc (Scan::check_non_pic): Allow R_X86_64_32 for x32.
+ (Scan::local): Use R_X86_64_RELATIVE relocation for R_X86_64_32
+ under x32.
+
+2012-01-09 H.J. Lu <hongjiu.lu@intel.com>
+
+ * x86_64.cc: Initial support for x32.
+
+2012-01-03 Cary Coutant <ccoutant@google.com>
+
+ * gold/incremental.cc (Sized_incremental_binary::do_process_got_plt):
+ Use abstract base class for GOT.
+ * gold/output.h (class Output_data_got_base): New abstract base class.
+ (class Output_data_got): Derive from new base class, adjust ctors.
+ (Output_data_got::reserve_slot): Make virtual; rename to
+ do_reserve_slot; Adjust callers.
+ * gold/target.h (Sized_target::init_got_plt_for_update): Return
+ pointer to abstract base class.
+ * gold/x86_64.cc (Target_x86_64::init_got_plt_for_update): Likewise.
+
+2011-12-18 Ian Lance Taylor <iant@google.com>
+
+ * object.h (Relobj::local_symbol_value): New function.
+ (Relobj::local_plt_offset): New function.
+ (Relobj::local_has_got_offset): New function.
+ (Relobj::local_got_offset): New function.
+ (Relobj::set_local_got_offset): New function.
+ (Relobj::do_local_symbol_value): New pure virtual function.
+ (Relobj::do_local_plt_offset): Likewise.
+ (Relobj::do_local_has_got_offset): Likewise.
+ (Relobj::do_local_got_offset): Likewise.
+ (Relobj::do_set_local_got_offset): Likewise.
+ (Sized_relobj::do_local_has_got_offset): Rename from
+ local_has_got_offset.
+ (Sized_relobj::do_local_got_offset): Rename from local_got_offset.
+ (Sized_relobj::do_set_local_got_offset): Rename from
+ set_local_got_offset.
+ (Sized_relobj_file::do_local_plt_offset): Rename from
+ local_plt_offset.
+ (Sized_relobj_file::do_local_symbol_value): New function.
+ * object.cc (Sized_relobj_file::do_local_plt_offset): Rename from
+ local_plt_offset.
+ * output.cc (Output_data_got::Got_entry::write): Change object to
+ Relobj. Use local_symbol_value.
+ (Output_data_got::add_global_with_rel): Change rel_dyn to
+ Output_data_reloc_generic*. Use add_global_generic.
+ (Output_data_got::add_global_with_rela): Remove. Change all
+ callers to use add_global_with_rel.
+ (Output_data_got::add_global_pair_with_rel): Change rel_dyn to
+ Output_data_reloc_generic*. Use add_global_generic.
+ (Output_data_got::add_global_pair_with_rela): Remove. Change all
+ callers to use add_global_pair_with_rel.
+ (Output_data_got::add_local): Change object to Relobj*.
+ (Output_data_got::add_local_plt): Likewise.
+ (Output_data_got::add_local_with_rel): Change object to Relobj*,
+ change rel_dyn to Output_data_reloc_generic*. Use
+ add_local_generic.
+ (Output_data_got::add_local_with_rela): Remove. Change all
+ callers to use all_local_with_rel.
+ (Output_data_got::add_local_pair_with_rel): Change object to
+ Relobj*, change rel_dyn to Output_data_reloc_generic*. Use
+ add_output_section_generic.
+ (Output_data_got::add_local_pair_with_rela): Remove. Change all
+ callers to use add_local_pair_with_rel.
+ (Output_data_got::reserve_local): Change object to Relobj*.
+ * output.h: (class Output_data_reloc_generic): Add pure virtual
+ declarations for add_global_generic, add_local_generic,
+ add_output_section_generic.
+ (class Output_data_reloc) [SHT_REL, SHT_RELA]: Implement new
+ functions for Output_data_reloc_generic. Update declarations for
+ changes listed in output.cc.
+ (class Output_data_got): Change template parameter to got_size.
+ Don't define Rel_dyn or Rela_dyn. Update declarations per above.
+ * incremental.h (Sized_relobj_incr::do_local_symbol_value): New
+ function.
+ (Sized_relobj_incr::do_local_plt_offset): New function.
+ * copy-relocs.cc (Copy_relocs::Copy_reloc_entry::emit): Call
+ add_global_generic.
+
+2011-12-17 Cary Coutant <ccoutant@google.com>
+
+ * dwarf_reader.cc (Sized_dwarf_line_info::read_lines): Add casts.
+ * resolve.cc (Symbol_table::resolve): Likewise.
+ * i386.cc (Target_i386::do_code_fill): Use char constants for nop
+ arrays.
+ * x86_64.cc (Target_x86_64::do_code_fill): Likewise.
+
+2011-12-16 Ian Lance Taylor <iant@google.com>
+
+ * output.h (Output_data_reloc_generic::add): Only call
+ add_dynamic_reloc if this is a dynamic reloc section.
+
+2011-12-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR gold/13505
+ * target-reloc.h (apply_relocation): Replace <64, false> with
+ <size, big_endian>.
+
+2011-11-25 Nick Clifton <nickc@redhat.com>
+
+ * po/it.po: New Italian translation.
+
+2011-11-17 Sterling Augustine <saugustine@google.com>
+
+ * script.cc (script_include_directive): Implement.
+ (read_script_file): New local variables name and search_path. Update
+ comment. Call IS_ABSOLUTE_PATH and Dirsearch::find_file_in_dir_list.
+ * dirsearch.h (Dirsearch::find_file_in_dir_list): Declare new method.
+ * dirsearch.cc (Dirsearch::find_file_in_dir_list): Implement it.
+
+2011-11-11 Sterling Augustine <saugustine@google.com>
+
+ * yyscript.y (section_cmd): Add support for INCLUDE directive.
+ (file_or_sections_cmd): Likewise.
+
2011-11-11 Doug Kwan <dougkwan@google.com>
* arm.cc (Target_arm::do_make_elf_object): Allow executable also
@@ -13,10 +936,39 @@
(Relocate_functions::rel32_unaligned): Ditto.
(Relocate_functions::pcrel32_unaligned): Ditto.
-2011-11-15 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
+2011-11-09 Doug Kwan <dougkwan@google.com>
+
+ PR gold/13362
+ * arm.cc (Arm_scan_relocatable_relocs::Default_scan_relocatable_relocs):
+ Use unaligned 4-byte relocs for static 32-bit data as required by EABI.
+ * reloc.h (Relocatable_relocs::Reloc_strategy): New enum
+ RELOC_ADJUST_FOR_SECTION_4_UNALIGNED.
+ (Relocate_functions::rel_unaligned): New.
+ (Relocate_functions::rel32_unaligned): New.
+ * target-reloc.h (relocate_for_relocatable): Add code to handle
+ RELOC_ADJUST_FOR_SECTION_4_UNALIGNED.
+ * testsuite/Makefile.am (arm_unaligned_reloc_r.stdout,
+ arm_unaligned_reloc_r): New targets.
+ * testsuite/Makefile.in: Regenerate.
+ * arm_unaligned_reloc.sh: Check unaligned relocs in relocatable
+ linking.
+
+2011-11-02 Ian Lance Taylor <iant@google.com>
+
+ * configure.ac: Add --with-lib-path option. Define LIB_PATH and
+ NATIVE_LINKER.
+ * Makefile.am (AM_CPPFLAGS): Define TOOLLIBDIR.
+ * options.cc (General_options::finalize): Use library search path
+ from configure script if specified. If not native and no sysroot,
+ only search TOOLLIBDIR.
+ * options.h (Search_directory::Search_directory): Change name to
+ const std::string&.
+ (General_options::add_to_library_path_with_sysroot): Change arg to
+ const std::string&.
+ * configure, Makefile.in, config.in: Rebuild.
+
+2011-11-02 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
- Apply mainline patches.
- 2011-11-02 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
* arm.cc (Target_arm::may_use_v5t_interworking): Check whether
we are working around the ARM1176 Erratum.
* options.h (General_options::fix_arm1176): Add option.
@@ -25,7 +977,9 @@
* testsuite/Makefile.in: Regenerate.
* testsuite/arm_fix_1176.s: New file.
* testsuite/arm_fix_1176.sh: Likewise.
- 2011-11-02 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
+
+2011-11-02 Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
+
* arm.cc (Target_arm::Target_arm): Remove initialisation of
may_use_blx_.
(Target_arm::may_use_blx): Remove method.
@@ -49,25 +1003,68 @@
* testsuite/arm_farcall_thumb_thumb.s: Likewise.
* testsuite/arm_farcall_thumb_thumb.sh: Likewise.
-2011-10-25 Alan Modra <amodra@gmail.com>
+2011-10-31 Cary Coutant <ccoutant@google.com>
- Apply mainline patches.
- 2011-09-26 Cary Coutant <ccoutant@google.com>
- gcc PR lto/47247
- * plugin.cc (get_symbols_v2): New function.
- (Plugin::load): Add LDPT_GET_SYMBOLS_V2.
- (is_referenced_from_outside): New function.
- (Pluginobj::get_symbol_resolution_info): Add version parameter, return
- LDPR_PREVAILING_DEF_IRONLY_EXP when using new version.
- (get_symbols): Pass version parameter.
- (get_symbols_v2): New function.
- * plugin.h (Pluginobj::get_symbol_resolution_info): Add version
- parameter.
- * testsuite/plugin_test.c (get_symbols_v2): New static variable.
- (onload): Add LDPT_GET_SYMBOLS_V2.
- (all_symbols_read_hook): Use get_symbols_v2; check for
- LDPR_PREVAILING_DEF_IRONLY_EXP.
- * testsuite/plugin_test_3.sh: Update expected results.
+ PR gold/13023
+ * expression.cc (Expression::eval_with_dot): Add
+ is_section_dot_assignment parameter.
+ (Expression::eval_maybe_dot): Likewise. Adjust value when rhs is
+ absolute and assigning to dot within a section.
+ * script-sections.cc
+ (Output_section_element_assignment::set_section_addresses): Pass
+ dot_section to set_if_absolute.
+ (Output_section_element_dot_assignment::finalize_symbols): Pass TRUE
+ as is_section_dot_assignment flag to eval_with_dot.
+ (Output_section_element_dot_assignment::set_section_addresses):
+ Likewise.
+ * script.cc (Symbol_assignment::set_if_absolute): Add dot_section
+ parameter. Also set value if relative to dot_section; set the
+ symbol's output_section.
+ * script.h (Expression::eval_with_dot): Add is_section_dot_assignment
+ parameter. Adjust all callers.
+ (Expression::eval_maybe_dot): Likewise.
+ (Symbol_assignment::set_if_absolute): Add dot_section parameter.
+ Adjust all callers.
+ * testsuite/script_test_2.t: Test assignment of an absolute value
+ to dot within an output section element.
+
+2011-10-31 Cary Coutant <ccoutant@google.com>
+
+ * options.h (class General_options): Add --[no-]gnu-unique options.
+ * symtab.cc (Symbol_table::sized_write_globals): Convert
+ STB_GNU_UNIQUE to STB_GLOBAL if --no-gnu-unique.
+
+2011-10-31 Cary Coutant <ccoutant@google.com>
+
+ PR gold/13359
+ * i386.cc (Target_i386::Relocate::relocate_tls): Remove
+ unnecessary assertion.
+ * x86_64.cc (Target_x86_64::Relocate::relocate_tls): Likewise.
+
+2011-10-31 Sriraman Tallam <tmsriram@google.com>
+
+ * symtab.h (Symbol_table::gc_mark_symbol_for_shlib): Rename to
+ gc_mark_symbol.
+ * symtab.cc (Symbol_table::gc_mark_symbol_for_shlib): Rename to
+ gc_mark_symbol.
+ Change to just keep the section associated with symbol.
+ (Symbol_table::add_from_relobj): Mark symbols as not garbage when
+ they are externally visible and --export-dynamic is turned on.
+ (Symbol_table::gc_mark_dyn_syms): Call gc_mark_symbol.
+
+2011-10-19 Ian Lance Taylor <iant@google.com>
+
+ PR gold/13163
+ * script-sections.cc
+ (Output_section_element_dot_assignment::needs_output_section): New
+ function.
+
+2011-10-19 Ian Lance Taylor <iant@google.com>
+
+ PR gold/13204
+ * layout.cc (Layout::segment_precedes): Don't assert failure if a
+ --section-start option was seen.
+ * options.h (General_options::any_section_start): New function.
2011-10-18 David S. Miller <davem@davemloft.net>
@@ -82,12 +1079,160 @@
__tls_get_addr call delay slot instruction forward 4 bytes when
performing relaxation.
+2011-10-18 Cary Coutant <ccoutant@google.com>
+
+ * output.cc (posix_fallocate): Return 0 on success, errno on failure.
+ (Output_file::map_no_anonymous): Check for non-zero
+ return code from posix_fallocate.
+
+2011-10-17 Cary Coutant <ccoutant@google.com>
+
+ PR gold/13245
+ * plugin.cc (is_visible_from_outside): Check for symbols
+ referenced from dynamic objects.
+ * resolve.cc (Symbol_table::resolve): Don't count references
+ from dynamic objects as references from real ELF files.
+ * testsuite/plugin_test_2.sh: Adjust expected result.
+
+2011-10-17 Cary Coutant <ccoutant@google.com>
+
+ * gold.cc: Include timer.h.
+ (queue_middle_tasks): Stamp time.
+ (queue_final_tasks): Likewise.
+ * main.cc (main): Store timer in parameters. Print timers
+ for each pass.
+ * parameters.cc (Parameters::Parameters): Initialize timer_.
+ (Parameters::set_timer): New function.
+ (set_parameters_timer): New function.
+ * parameters.h (Parameters::set_timer): New function.
+ (Parameters::timer): New function.
+ (Parameters::timer_): New data member.
+ (set_parameters_timer): New function.
+ * timer.cc (Timer::stamp): New function.
+ (Timer::get_pass_time): New function.
+ * timer.h (Timer::stamp): New function.
+ (Timer::get_pass_time): New function.
+ (Timer::pass_times_): New data member.
+
+2011-10-17 Cary Coutant <ccoutant@google.com>
+
+ * readsyms.cc (Read_symbols::run): Don't queue an unblocker
+ task for members of lib groups.
+
+2011-10-17 Cary Coutant <ccoutant@google.com>
+
+ PR gold/13288
+ * fileread.cc (File_read::find_view): Add assert.
+ (File_read::make_view): Move bounds check (replace with assert)...
+ (File_read::find_or_make_view): ... to here.
+
+2011-10-12 Cary Coutant <ccoutant@google.com>
+
+ * output.cc (Output_file::open_base_file): Handle case where
+ ::read returns less than requested size.
+
+2011-10-10 Cary Coutant <ccoutant@google.com>
+
+ * incremental.cc (Sized_relobj_incr::Sized_relobj_incr):
+ Initialize defined_count_.
+ (Sized_relobj_incr::do_add_symbols): Count defined symbols.
+ (Sized_relobj_incr::do_get_global_symbol_counts): Rewrite.
+ (Sized_incr_dynobj::Sized_incr_dynobj): Initialize defined_count_.
+ (Sized_incr_dynobj::do_add_symbols): Count defined symbols.
+ (Sized_incr_dynobj::do_get_global_symbol_counts): Rewrite.
+ * incremental.h (Sized_relobj_incr::defined_count_): New data
+ member.
+ (Sized_incr_dynobj::defined_count_): New data member.
+ * plugin.cc (Sized_pluginobj::do_get_global_symbol_counts):
+ Return zeroes instead of internal error.
+
+2011-10-10 Cary Coutant <ccoutant@google.com>
+
+ PR gold/13249
+ * output.cc (Output_reloc::Output_reloc): Add use_plt_offset flag.
+ (Output_reloc::symbol_value): Return PLT offset if flag is set.
+ * output.h (class Output_reloc): Add use_plt_offset flag.
+ (Output_reloc::type_): Adjust size of bit field.
+ (Output_reloc::use_plt_offset_): New bit field.
+ (class Output_data_reloc): Adjust all calls to Output_reloc_type.
+ (Output_data_reloc::add_local_relative): (RELA only) Add use_plt_offset
+ flag. Adjust all callers.
+ * x86_64.cc (Target_x86_64::Scan::local): Check for IFUNC when
+ creating RELATIVE relocations.
+
+2011-10-10 Nick Clifton <nickc@redhat.com>
+
+ * po/es.po: Updated Spanish translation.
+ * po/fi.po: Updated Finnish translation.
+
+2011-10-03 Diego Novillo <dnovillo@google.com>
+
+ * options.cc (parse_uint): Fix dereference of RETVAL.
+
+2011-09-29 Sriraman Tallam <tmsriram@google.com>
+
+ * layout.h (section_order_map_): New member.
+ (get_section_order_map): New member function.
+ * output.cc (Output_section::add_input_section): Check for patterns
+ only when --section-ordering-file is specified.
+ * gold.cc (queue_middle_tasks): Delay updating order of sections till
+ output_sections have been formed.
+ * layout.cc (Layout_Layout): Initialize section_order_map_.
+ * plugin.cc (update_section_order): Store order in order_map. Do not
+ update the order.
+ * testsuite/Makefile.am: Add test case for plugin_final_layout.
+ * testsuite/Makefile.in: Regenerate.
+ * testsuite/plugin_section_order.c: New file.
+ * testsuite/plugin_final_layout.cc: New file.
+ * testsuite/plugin_final_layout.sh: New file.
+
+2011-09-29 Cary Coutant <ccoutant@google.com>
+
+ * incremental.cc (Sized_incremental_binary::do_process_got_plt):
+ Check for NULL.
+ * symtab.cc (Symbol_table::add_from_relobj): Ignore version
+ symbols during incremental update.
+ (Symbol_table::add_from_dynobj): Likewise.
+
2011-09-27 Viktor Kutuzov <vkutuzov@accesssoftek.com>
Ian Lance Taylor <iant@google.com>
* symtab.cc (Symbol_table::define_special_symbol): Always
canonicalize version string.
+2011-09-26 Cary Coutant <ccoutant@google.com>
+
+ * gold.cc (queue_initial_tasks): Move option checks ...
+ * options.cc (General_options::finalize): ... to here. Disable
+ some options; make others fatal.
+
+2011-09-26 Cary Coutant <ccoutant@google.com>
+
+ gcc PR lto/47247
+ * plugin.cc (get_symbols_v2): New function.
+ (Plugin::load): Add LDPT_GET_SYMBOLS_V2.
+ (is_referenced_from_outside): New function.
+ (Pluginobj::get_symbol_resolution_info): Add version parameter, return
+ LDPR_PREVAILING_DEF_IRONLY_EXP when using new version.
+ (get_symbols): Pass version parameter.
+ (get_symbols_v2): New function.
+ * plugin.h (Pluginobj::get_symbol_resolution_info): Add version
+ parameter.
+ * testsuite/plugin_test.c (get_symbols_v2): New static variable.
+ (onload): Add LDPT_GET_SYMBOLS_V2.
+ (all_symbols_read_hook): Use get_symbols_v2; check for
+ LDPR_PREVAILING_DEF_IRONLY_EXP.
+ * testsuite/plugin_test_3.sh: Update expected results.
+
+2011-09-23 Simon Baldwin <simonb@google.com>
+
+ * configure.ac: Add new --with-gold-ldadd and --with-gold-ldflags
+ configuration options.
+ * configure: Regenerate.
+ * Makefile.am: Handle GOLD_LDADD and GOLD_LDFLAGS.
+ * Makefile.in: Regenerate.
+ * testsuite/Makefile.in: Regenerate.
+
2011-09-19 Sriraman Tallam <tmsriram@google.com>
* plugin.h (should_defer_layout): Modify to check for any_claimed_.
@@ -292,7 +1437,7 @@
(get_section_name): New function.
(get_section_contents): New function.
(update_section_order): New function.
- (allow_section_ordering): New function.
+ (allow_section_ordering): New function.
(Plugin::load): Add the new interfaces to the transfer vector.
(Plugin_manager::load_plugins): New parameter.
(Plugin_manager::all_symbols_read): New parameter.
@@ -1201,7 +2346,7 @@
* output.cc: Likewise.
2011-05-31 Doug Kwan <dougkwan@google.com>
- Asier Llano
+ Asier Llano
PR gold/12826
* arm.cc (Target_arm::tag_cpu_arch_combine): Fix handling of
@@ -1358,7 +2503,7 @@
(Incremental_input_entry_reader::get_global_symbol_count): Rewrite.
(Incremental_input_entry_reader::get_output_symbol_index): Adjust
size of shared library info entry.
- * layout.cc (Layout::finish_dynamic_section): Don't test for
+ * layout.cc (Layout::finish_dynamic_section): Don't test for
incremental link when adding DT_NEEDED entries.
* object.h (Object::Object): Initialize new data member.
(Object::dynobj): New function.
@@ -1688,7 +2833,7 @@
* arm.cc (Arm_output_section::Arm_output_section): Set SHF_LINK_ORDER
flag of a SHT_ARM_EXIDX section.
- * testsuite/Makefile.am (arm_exidx_test): New test rules.
+ * testsuite/Makefile.am (arm_exidx_test): New test rules.
* testsuite/Makefile.in: Regenerate.
* testsuite/arm_exidx_test.s: New file.
* testsuite/arm_exidx_test.sh: Same.
@@ -2444,9 +3589,9 @@
2011-02-02 Sriraman Tallam <tmsriram@google.com>
* icf.h (is_section_foldable_candidate): Change type of parameter
- to std::string.
+ to std::string.
* icf.cc (Icf::find_identical_sections): Change type of local variable
- section_name to be std::string.
+ section_name to be std::string.
(is_function_ctor_or_dtor): Change type of parameter to std::string.
2011-01-25 Ian Lance Taylor <iant@google.com>
@@ -2714,7 +3859,7 @@
(Arm_exidx_merge_section::section_contents_): New data member.
(Arm_input_section::Arm_input_section): Initialize original_contents_.
(Arm_input_section::~Arm_input_section): De-allocate memory.
- (Arm_input_section::original_contents_): New data member.
+ (Arm_input_section::original_contents_): New data member.
(Arm_exidx_fixup::process_exidx_section): Pass EXIDX section contents
in parameters instead of calling Object::section_contents without
locking.
@@ -2735,7 +3880,7 @@
and updating local symbols.
(Arm_input_section<big_endian>::init): Copy contents of original
input section.
- (Arm_input_section<big_endian>::do_write): Use saved contents of
+ (Arm_input_section<big_endian>::do_write): Use saved contents of
original input section instead of calling Object::section_contents
without locking.
(Arm_exidx_cantunwind::do_fixed_endian_write): Find out text section
@@ -2743,7 +3888,7 @@
(Arm_exidx_merged_section::Arm_exidx_merged_section): Add sanity check
for size. Allocate a buffer for merged EXIDX entries.
(Arm_exidx_merged_section::build_contents): New method.
- (Arm_exidx_merged_section::do_write): Move merge section contents
+ (Arm_exidx_merged_section::do_write): Move merge section contents
building code to Arm_exidx_merged_section::build_contetns. Write
out contetns in buffer instead of building it on the fly.
(Arm_relobj::make_exidx_input_section): Also pass text section size
@@ -2802,7 +3947,7 @@
2010-10-29 Viktor Kutuzov <vkutuzov@accesssoftek.com>
* testsuite/Makefile.am: Move gcctestdir/ld rule to
- NATIVE_OR_CROSS_LINKER.
+ NATIVE_OR_CROSS_LINKER.
* testsuite/Makefile.in: Regenerate.
2010-10-20 Doug Kwan <dougkwan@google.com>
@@ -2829,43 +3974,43 @@
2010-10-14 Cary Coutant <ccoutant@google.com>
* debug.h (DEBUG_INCREMENTAL): New flag.
- (debug_string_to_enum): Add DEBUG_INCREMENTAL).
- * gold.cc (queue_initial_tasks): Check parameters for incremental link
- mode.
- * incremental.cc (report_command_line): Ignore all forms of
- --incremental.
- * layout.cc (Layout::Layout): Check parameters for incremental link
- mode.
- * options.cc (General_options::parse_incremental): New function.
- (General_options::parse_no_incremental): New function.
- (General_options::parse_incremental_full): New function.
- (General_options::parse_incremental_update): New function.
- (General_options::incremental_mode_): New data member.
- (General_options::finalize): Check incremental_mode_.
- * options.h (General_options): Update help text for --incremental.
- Add --no-incremental, --incremental-full, --incremental-update.
- (General_options::Incremental_mode): New enum type.
- (General_options::incremental_mode): New function.
- (General_options::incremental_mode_): New data member.
- * parameters.cc (Parameters::incremental_mode_): New data member.
- (Parameters::set_options): Set incremental_mode_.
- (Parameters::set_incremental_full): New function.
- (Parameters::incremental): New function.
- (Parameters::incremental_update): New function.
- (set_parameters_incremental_full): New function.
- * parameters.h (Parameters::set_incremental_full): New function.
- (Parameters::incremental): New function.
- (Parameters::incremental_update): New function.
- (Parameters::incremental_mode_): New data member.
- (set_parameters_incremental_full): New function.
- * plugin.cc (Plugin_manager::add_input_file): Check parameters for
- incremental link mode.
- * reloc.cc (Sized_relobj::do_read_relocs): Likewise.
- (Sized_relobj::do_relocate_sections): Likewise.
- * testsuite/Makefile.am (incremental_test): Use --incremental-full
- option.
- * testsuite/Makefile.in: Regenerate.
- * testsuite/incremental_test.sh: Filter all forms of --incremental.
+ (debug_string_to_enum): Add DEBUG_INCREMENTAL).
+ * gold.cc (queue_initial_tasks): Check parameters for incremental link
+ mode.
+ * incremental.cc (report_command_line): Ignore all forms of
+ --incremental.
+ * layout.cc (Layout::Layout): Check parameters for incremental link
+ mode.
+ * options.cc (General_options::parse_incremental): New function.
+ (General_options::parse_no_incremental): New function.
+ (General_options::parse_incremental_full): New function.
+ (General_options::parse_incremental_update): New function.
+ (General_options::incremental_mode_): New data member.
+ (General_options::finalize): Check incremental_mode_.
+ * options.h (General_options): Update help text for --incremental.
+ Add --no-incremental, --incremental-full, --incremental-update.
+ (General_options::Incremental_mode): New enum type.
+ (General_options::incremental_mode): New function.
+ (General_options::incremental_mode_): New data member.
+ * parameters.cc (Parameters::incremental_mode_): New data member.
+ (Parameters::set_options): Set incremental_mode_.
+ (Parameters::set_incremental_full): New function.
+ (Parameters::incremental): New function.
+ (Parameters::incremental_update): New function.
+ (set_parameters_incremental_full): New function.
+ * parameters.h (Parameters::set_incremental_full): New function.
+ (Parameters::incremental): New function.
+ (Parameters::incremental_update): New function.
+ (Parameters::incremental_mode_): New data member.
+ (set_parameters_incremental_full): New function.
+ * plugin.cc (Plugin_manager::add_input_file): Check parameters for
+ incremental link mode.
+ * reloc.cc (Sized_relobj::do_read_relocs): Likewise.
+ (Sized_relobj::do_relocate_sections): Likewise.
+ * testsuite/Makefile.am (incremental_test): Use --incremental-full
+ option.
+ * testsuite/Makefile.in: Regenerate.
+ * testsuite/incremental_test.sh: Filter all forms of --incremental.
2010-10-12 Viktor Kutuzov <vkutuzov@accesssoftek.com>
@@ -3900,7 +5045,7 @@
section without SHF_EXECINSTR.
(Arm_output_section::fix_exidx_coverage): Skip input sections with
errors.
- (Arm_relobj::make_exidx_input_section): Add new parameter for text
+ (Arm_relobj::make_exidx_input_section): Add new parameter for text
section header. Make error messages more verbose. Check for
a non-executable section linked to an EXIDX section.
(Arm_relobj::do_read_symbols): Remove error checking, which has been
@@ -3912,7 +5057,7 @@
in a relocatable link.
(Target_arm::do_relax): Look for the EXIDX output section instead of
assuming that it is called .ARM.exidx.
- (Target_arm::fix_exidx_coverage): Add a new parameter for input
+ (Target_arm::fix_exidx_coverage): Add a new parameter for input
section list. Do not check for SHF_EXECINSTR section flags but
skip any input section with errors.
* output.cc (Output_section::Output_section): Initialize
@@ -4271,15 +5416,15 @@
to use Output_section_lookup_maps class.
(Output_section::add_relaxed_input_section): Adjst code for lookup
maps code refactoring.
- (Output_section::add_merge_input_section): Add a new parameter
+ (Output_section::add_merge_input_section): Add a new parameter
KEEPS_INPUT_SECTION. Adjust code to use Output_section_lookup_maps
class. If adding input section to a newly created merge output
section fails, remove the new merge section.
(Output_section::convert_input_sections_in_list_to_relaxed_input_sections):
Adjust code for use of the Output_section_lookup_maps class.
- (Output_section::find_merge_section): Ditto.
+ (Output_section::find_merge_section): Ditto.
(Output_section::build_lookup_maps): New method defintion.
- (Output_section::find_relaxed_input_section): Adjust code to use
+ (Output_section::find_relaxed_input_section): Adjust code to use
Output_section_lookup_maps class.
(Output_section::get_input_sections): Export merge sections. Adjust
code to use Output_section_lookup_maps class.
@@ -4297,12 +5442,12 @@
defintion. Declare method only.
(Output_section::Input_section::shndx): Ditto.
(Output_section::Input_section::output_merge_base): New method defintion.
- (Output_section::Input_section::u2_.pomb): New union field.
+ (Output_section::Input_section::u2_.pomb): New union field.
(Output_section::Merge_section_by_properties_map,
Output_section::Output_section_data_by_input_section_map,
Output_section::Ouptut_relaxed_input_section_by_input_section_map):
Remove types.
- (Output_section::add_merge_input_section): Add new parameter
+ (Output_section::add_merge_input_section): Add new parameter
KEEPS_INPUT_SECTIONS.
(Output_section::build_lookup_maps): New method declaration.
(Output_section::merge_section_map_,
@@ -4578,7 +5723,7 @@
section elements. Handle discard sections.
(Sort_output_sections::operator()): Handle NOLOAD sections.
* script-sections.h (Script_sections::Section_type): New enum type.
- (Script_sections::output_section_name): Add a new parameter for
+ (Script_sections::output_section_name): Add a new parameter for
returning script section type.
* script.cc (script_keyword_parsecodes): Add keywords COPY, DSECT,
INFO and NOLOAD.
@@ -4749,7 +5894,7 @@
thumb2_blx_in_range, thumb2_blx_in_range.o,
thumb2_blx_out_of_range.stdout, thumb2_blx_out_of_range,
thumb2_blx_out_of_range.o): New rules.
- (MOSTLYCLEANFILES): Add thumb_blx_in_range, thumb_blx_out_of_range,
+ (MOSTLYCLEANFILES): Add thumb_blx_in_range, thumb_blx_out_of_range,
thumb2_blx_in_range and thumb2_blx_out_of_range.
* testsuite/Makefile.in: Regenerate.
* arm_branch_in_range.sh: Add tests for THUMB BLX.
@@ -4815,13 +5960,13 @@
Stub_table::reloc_stubs_size_ and Stub_table::reloc_stubs_addralign_.
(Stub_table::reloc_stubs_size_, Stub_table::reloc_stubs_addralign_):
New data members.
- (Stub_table::update_data_size_and_addralign): Use
+ (Stub_table::update_data_size_and_addralign): Use
Stub_table::reloc_stubs_size_ and Stub_table::reloc_stubs_addralign_
instead of going over all reloc stubs.
- (Stub_table::finalize_stubs): Do not assign reloc stub offsets.
+ (Stub_table::finalize_stubs): Do not assign reloc stub offsets.
* stringpool.cc (Stringpool_template::Stringpool_template): Initialize
Stringpool_template::offset_ to size of Stringpool_char.
- (Stringpool_template::new_key_offset): Remove code to initialize
+ (Stringpool_template::new_key_offset): Remove code to initialize
Stringpool_template::offset_.
* stringpool.h (Stringpool_template::set_no_zero_null): Set
Stringpool_template::offset_ to zero.
@@ -4837,10 +5982,10 @@
when not optimizing.
* stringpool.h (Chunked_vector::Chunked_vector): Initialize data
member size_.
- (Chunked_vector::clear): Clear size_.
- (Chunked_vector::reserve): Call reserve method of all Element_vectors.
- (Chunked_vector::size): Return size_.
- (Chunked_vector::push_back): Use size_ to find insert position.
+ (Chunked_vector::clear): Clear size_.
+ (Chunked_vector::reserve): Call reserve method of all Element_vectors.
+ (Chunked_vector::size): Return size_.
+ (Chunked_vector::push_back): Use size_ to find insert position.
(Chunked_vector::size_): New data member.
(Stringpool_template::set_no_zero_null): Assert string set is empty.
(Stringpool_template::new_key_offset): New method declaration.
@@ -5043,7 +6188,7 @@
flags and attributes merging if an input file is a binary file.
* fileread.cc (Input_file::open): Record format of original file.
* fileread.h (Input_file::Format): New enum type.
- (Input_file::Input_file): Initialize data member format_.
+ (Input_file::Input_file): Initialize data member format_.
(Input_file::format): New method definition.
(Input_file::format_):: New data member.
@@ -5055,7 +6200,7 @@
(Arm_output_section::fix_exidx_coverage): Add a parameter for layout.
If user uses a script with a SECTIONS clause, issue only a warning
for a misplaced EXIDX input section. Otherwise, issue an error.
- (Arm_relobj::do_gc_process_relocs): Exit early if we are not doing
+ (Arm_relobj::do_gc_process_relocs): Exit early if we are not doing
garbage collection.
(Target_arm::got_mode_index_entry): Handle static linking.
(Target_arm::Scan::local): Ditto.
@@ -5093,7 +6238,7 @@
* arm.cc (Arm_relocate_functions::arm_branch_common): Fix bug in
handling of the maximum backward branch offset.
- (Arm_relocate_functions::thumb_branch_common): Ditto.
+ (Arm_relocate_functions::thumb_branch_common): Ditto.
* testsuite/Makefile.am (check_SCRIPTS): Add arm_branch_in_range.sh.
(check_DATA): Add arm_bl_in_range.stdout, arm_bl_out_of_range.stdout
thumb_bl_in_range.stdout, thumb_bl_out_of_range.stdout,
@@ -5147,7 +6292,7 @@
(Target_arm::optimize_tls_reloc, Target_arm::define_tls_base_symbol,
Target_arm::got_mod_index_entry, Target_arm::rel_tls_desc_section):
New methods.
- (Target_arm::Got_type): Add GOT_TYPE_TLS_NOFFSET, GOT_TYPE_OFFSET,
+ (Target_arm::Got_type): Add GOT_TYPE_TLS_NOFFSET, GOT_TYPE_OFFSET,
GOT_TYPE_TLS_PAIR and GOT_TYPE_TLS_DESC.
(Target_arm::got_mod_index_offset_,
Target_arm::tls_base_symbol_defined_): New data members.
@@ -5489,8 +6634,8 @@
* Makefile.am (HFILES): Add arm-reloc-property.h.
(DEFFILES): New.
- (TARGETSOURCES): Add arm-reloc-property.cc
- (ALL_TARGETOBJS): Add arm-reloc-property.$(OBJEXT)
+ (TARGETSOURCES): Add arm-reloc-property.cc
+ (ALL_TARGETOBJS): Add arm-reloc-property.$(OBJEXT)
(libgold_a_SOURCES): $(DEFFILES)
* Makefile.in: Regenerate.
* arm-reloc-property.cc: New file.
@@ -5609,14 +6754,14 @@
* arm.cc (set): Include.
(class Arm_exidx_fixup): Change type of last_input_section_ to const
pointer type.
- (Arm_output_section::Text_section_list): New type.
+ (Arm_output_section::Text_section_list): New type.
(Arm_output_section::append_text_sections_to_list): New method.
(Arm_output_section::fix_exidx_coverage): Ditto.
(Arm_relobj::Arm_relobj): Initialize exidx_section_map_.
- (Arm_relobj::convert_input_section_to_relaxed_section): Use
+ (Arm_relobj::convert_input_section_to_relaxed_section): Use
Relobj::set_section_offset() instead of
Sized_relobj::invalidate_section_offset().
- (Arm_relobj::section_needs_reloc_stub_scanning): Add an extra
+ (Arm_relobj::section_needs_reloc_stub_scanning): Add an extra
parameter for section headers. Ignore relocation sections for
unallocated sections and EXIDX sections.
(Target_arm::fix_exidx_coverage): New method.
@@ -5628,7 +6773,7 @@
(Arm_output_section::append_text_sections_to_list): New method.
(Arm_output_section::fix_exidx_coverage): Ditto.
(Arm_relobj::scan_sections_for_stubs): Adjust call to
- Arm_relobj::section_needs_reloc_stub_scanning.
+ Arm_relobj::section_needs_reloc_stub_scanning.
(Target_arm::do_relax): Fix EXIDX output section coverage in the
first pass.
(Target_arm::fix_exidx_coverage): New method.
@@ -5720,11 +6865,11 @@
(Output_section::add_merge_input_section): Ditto.
(Output_section::build_relaxation_map): Change to use Section_id
instead of Input_section_specifier as key type.
- (Output_section::convert_input_sections_in_list_to_relaxed_sections):
+ (Output_section::convert_input_sections_in_list_to_relaxed_sections):
Ditto.
(Output_section::convert_input_sections_to_relaxed_sections): Change
to use Const_section_id instead of Input_section_specifier as key type.
- (Output_section::find_merge_section): Ditto.
+ (Output_section::find_merge_section): Ditto.
(Output_section::find_relaxed_input_section): Ditto.
* output.h (Input_section_specifier): Remove class.
(Output_section::Output_section_data_by_input_section_map): Change
@@ -5996,7 +7141,7 @@
Stub_table::update_data_size_and_addralign,
Stub_table::apply_cortex_a8_workaround_to_address_range): New method
definitions.
- (Stub_table::relocate_stubs): Handle Cortex-A8 stubs.
+ (Stub_table::relocate_stubs): Handle Cortex-A8 stubs.
(Stub_table::do_write): Ditto.
(Target_arm::do_relax): Adjust code for changes in Stub_table.
@@ -6707,7 +7852,7 @@
(Arm_dynobj::attributes_section_data_): New data member declaration.
(Target_arm::Target_arm): Initialize attributes_section_data_. Change
initialization value of may_use_blx_ to false.
- (Target_arm::using_thumb2, Target_arm::using_thumb_only,
+ (Target_arm::using_thumb2, Target_arm::using_thumb_only,
Target_arm::may_use_arm_nop, Target_arm::may_use_thumb2_nop): Use
object attributes to compute results instead of hard-coding.
(Target_arm::do_attribute_arg_type, Target_arm::do_attributes_order,
@@ -7698,7 +8843,7 @@
base class initializer.
(Output_section::add_relaxed_input_section): New method declaration.
(Output_section::Input_section): Change visibility to protected.
- (Output_section::Input_section::relobj,
+ (Output_section::Input_section::relobj,
Output_section::Input_section::shndx): Handle relaxed input sections.
Output_section::input_sections) Change visibility to protected. Also
define overload to return a non-const pointer.
@@ -8124,7 +9269,7 @@
Output_section_data.
(Output_data_dynamic::set_final_data_size): Add DT_NULL tag only once.
(Output_symtab_xindex::do_write): Add array bound check.
- (Output_section::Input_section::print_to_mapfile): Handle
+ (Output_section::Input_section::print_to_mapfile): Handle
RELAXED_INPUT_SECTION_CODE.
(Output_section::Output_section): Initialize data member checkpoint_.
(Output_section::~Output_section): Delete checkpoint object pointed
@@ -8351,7 +9496,7 @@
an elfcpp:Ehdr as parameter.
* target.cc: Include dynobj.h.
(Target::do_make_elf_object_implementation): New.
- (Target::do_make_elf_object): New.
+ (Target::do_make_elf_object): New.
* target.h (Target::make_elf_object): New template declaration.
(Target::do_make_elf_object): New method declarations.
(Target::do_make_elf_object_implementation): New template declaration.
@@ -8612,7 +9757,7 @@
* Makefile.am (libgold_a_LIBADD): New.
(ld_new_DEPENDENCIES, ld_new_LDADD): Remove LIBOBJS
- * Makefile.in: Regenerate.
+ * Makefile.in: Regenerate.
* config.in (HAVE_DECL_MEMMEM, HAVE_DECL_STRNDUP): New.
* configure: Regenerate.
* configure.ac (AC_CHECK_DECLS): Add strndup and memmem.
@@ -9538,11 +10683,11 @@
dispositions.
* options.cc (General_options::parse_incremental_changed): New
function.
- (General_options::parse_incremental_unchanged): New function.
- (General_options::parse_incremental_unknown): New function.
- (General_options::General_options): Initialize new fields
+ (General_options::parse_incremental_unchanged): New function.
+ (General_options::parse_incremental_unknown): New function.
+ (General_options::General_options): Initialize new fields
incremental_disposition_ and implicit_incremental_.
- (General_options::finalize): Check for uasge of --incremental-*
+ (General_options::finalize): Check for uasge of --incremental-*
without --incremental.
2009-02-06 Chris Demetriou <cgd@google.com>
@@ -9582,7 +10727,7 @@
2009-01-31 Mikolaj Zalewski <mikolajz@google.com>
* script.cc (Lazy_demangler): New class.
- (Version_script_info::get_symbol_version_helper): Demangle a
+ (Version_script_info::get_symbol_version_helper): Demangle a
symbol only once.
2009-01-29 Cary Coutant <ccoutant@google.com>
diff --git a/binutils-2.22/gold/Makefile.am b/binutils-2.22/gold/Makefile.am
index df5e66c..72ffdf5 100644
--- a/binutils-2.22/gold/Makefile.am
+++ b/binutils-2.22/gold/Makefile.am
@@ -15,7 +15,7 @@ AM_CPPFLAGS = \
-I$(srcdir) -I$(srcdir)/../include -I$(srcdir)/../elfcpp \
-DLOCALEDIR="\"$(datadir)/locale\"" \
-DBINDIR="\"$(bindir)\"" -DTOOLBINDIR="\"$(tooldir)/bin\"" \
- @INCINTL@
+ -DTOOLLIBDIR="\"$(tooldir)/lib\"" @INCINTL@
LIBIBERTY = ../libiberty/libiberty.a
@@ -55,6 +55,7 @@ CCFILES = \
expression.cc \
fileread.cc \
gc.cc \
+ gdb-index.cc \
gold.cc \
gold-threads.cc \
icf.cc \
@@ -63,6 +64,7 @@ CCFILES = \
layout.cc \
mapfile.cc \
merge.cc \
+ nacl.cc \
object.cc \
options.cc \
output.cc \
@@ -102,6 +104,7 @@ HFILES = \
fileread.h \
freebsd.h \
gc.h \
+ gdb-index.h \
gold.h \
gold-threads.h \
icf.h \
@@ -109,6 +112,7 @@ HFILES = \
layout.h \
mapfile.h \
merge.h \
+ nacl.h \
object.h \
options.h \
output.h \
@@ -151,12 +155,14 @@ libgold_a_LIBADD = $(LIBOBJS)
sources_var = main.cc
deps_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL_DEP)
-ldadd_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL) \
+ldadd_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(GOLD_LDADD) $(LIBINTL) \
$(THREADSLIB) $(LIBDL)
+ldflags_var = $(GOLD_LDFLAGS)
ld_new_SOURCES = $(sources_var)
ld_new_DEPENDENCIES = $(deps_var)
ld_new_LDADD = $(ldadd_var)
+ld_new_LDFLAGS = $(ldflags_var)
EXTRA_ld_new_SOURCES = $(TARGETSOURCES)
diff --git a/binutils-2.22/gold/Makefile.in b/binutils-2.22/gold/Makefile.in
index 1c33fe6..356b1d6 100644
--- a/binutils-2.22/gold/Makefile.in
+++ b/binutils-2.22/gold/Makefile.in
@@ -52,6 +52,7 @@ DIST_COMMON = NEWS README ChangeLog $(srcdir)/Makefile.in \
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
$(top_srcdir)/../config/gettext-sister.m4 \
+ $(top_srcdir)/../config/lcmessage.m4 \
$(top_srcdir)/../config/lead-dot.m4 \
$(top_srcdir)/../config/nls.m4 \
$(top_srcdir)/../config/override.m4 \
@@ -77,16 +78,17 @@ am__objects_1 = archive.$(OBJEXT) attributes.$(OBJEXT) \
descriptors.$(OBJEXT) dirsearch.$(OBJEXT) dynobj.$(OBJEXT) \
dwarf_reader.$(OBJEXT) ehframe.$(OBJEXT) errors.$(OBJEXT) \
expression.$(OBJEXT) fileread.$(OBJEXT) gc.$(OBJEXT) \
- gold.$(OBJEXT) gold-threads.$(OBJEXT) icf.$(OBJEXT) \
- incremental.$(OBJEXT) int_encoding.$(OBJEXT) layout.$(OBJEXT) \
- mapfile.$(OBJEXT) merge.$(OBJEXT) object.$(OBJEXT) \
- options.$(OBJEXT) output.$(OBJEXT) parameters.$(OBJEXT) \
- plugin.$(OBJEXT) readsyms.$(OBJEXT) \
- reduced_debug_output.$(OBJEXT) reloc.$(OBJEXT) \
- resolve.$(OBJEXT) script-sections.$(OBJEXT) script.$(OBJEXT) \
- stringpool.$(OBJEXT) symtab.$(OBJEXT) target.$(OBJEXT) \
- target-select.$(OBJEXT) timer.$(OBJEXT) version.$(OBJEXT) \
- workqueue.$(OBJEXT) workqueue-threads.$(OBJEXT)
+ gdb-index.$(OBJEXT) gold.$(OBJEXT) gold-threads.$(OBJEXT) \
+ icf.$(OBJEXT) incremental.$(OBJEXT) int_encoding.$(OBJEXT) \
+ layout.$(OBJEXT) mapfile.$(OBJEXT) merge.$(OBJEXT) \
+ nacl.$(OBJEXT) object.$(OBJEXT) options.$(OBJEXT) \
+ output.$(OBJEXT) parameters.$(OBJEXT) plugin.$(OBJEXT) \
+ readsyms.$(OBJEXT) reduced_debug_output.$(OBJEXT) \
+ reloc.$(OBJEXT) resolve.$(OBJEXT) script-sections.$(OBJEXT) \
+ script.$(OBJEXT) stringpool.$(OBJEXT) symtab.$(OBJEXT) \
+ target.$(OBJEXT) target-select.$(OBJEXT) timer.$(OBJEXT) \
+ version.$(OBJEXT) workqueue.$(OBJEXT) \
+ workqueue-threads.$(OBJEXT)
am__objects_2 =
am__objects_3 = yyscript.$(OBJEXT)
am_libgold_a_OBJECTS = $(am__objects_1) $(am__objects_2) \
@@ -101,7 +103,9 @@ am_ld_new_OBJECTS = $(am__objects_4)
ld_new_OBJECTS = $(am_ld_new_OBJECTS)
am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) libgold.a $(LIBIBERTY) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+ld_new_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(ld_new_LDFLAGS) \
+ $(LDFLAGS) -o $@
@GCC_TRUE@@NATIVE_LINKER_TRUE@am_ld1_OBJECTS = $(am__objects_4)
ld1_OBJECTS = $(am_ld1_OBJECTS)
ld1_LINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(ld1_LDFLAGS) \
@@ -251,6 +255,8 @@ EGREP = @EGREP@
EXEEXT = @EXEEXT@
GENCAT = @GENCAT@
GMSGFMT = @GMSGFMT@
+GOLD_LDADD = @GOLD_LDADD@
+GOLD_LDFLAGS = @GOLD_LDFLAGS@
GREP = @GREP@
INCINTL = @INCINTL@
INSTALL = @INSTALL@
@@ -365,7 +371,7 @@ AM_CPPFLAGS = \
-I$(srcdir) -I$(srcdir)/../include -I$(srcdir)/../elfcpp \
-DLOCALEDIR="\"$(datadir)/locale\"" \
-DBINDIR="\"$(bindir)\"" -DTOOLBINDIR="\"$(tooldir)/bin\"" \
- @INCINTL@
+ -DTOOLLIBDIR="\"$(tooldir)/lib\"" @INCINTL@
LIBIBERTY = ../libiberty/libiberty.a
@PLUGINS_TRUE@LIBDL = -ldl
@@ -395,6 +401,7 @@ CCFILES = \
expression.cc \
fileread.cc \
gc.cc \
+ gdb-index.cc \
gold.cc \
gold-threads.cc \
icf.cc \
@@ -403,6 +410,7 @@ CCFILES = \
layout.cc \
mapfile.cc \
merge.cc \
+ nacl.cc \
object.cc \
options.cc \
output.cc \
@@ -442,6 +450,7 @@ HFILES = \
fileread.h \
freebsd.h \
gc.h \
+ gdb-index.h \
gold.h \
gold-threads.h \
icf.h \
@@ -449,6 +458,7 @@ HFILES = \
layout.h \
mapfile.h \
merge.h \
+ nacl.h \
object.h \
options.h \
output.h \
@@ -488,12 +498,14 @@ libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES) $(DEFFILES)
libgold_a_LIBADD = $(LIBOBJS)
sources_var = main.cc
deps_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL_DEP)
-ldadd_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL) \
+ldadd_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(GOLD_LDADD) $(LIBINTL) \
$(THREADSLIB) $(LIBDL)
+ldflags_var = $(GOLD_LDFLAGS)
ld_new_SOURCES = $(sources_var)
ld_new_DEPENDENCIES = $(deps_var)
ld_new_LDADD = $(ldadd_var)
+ld_new_LDFLAGS = $(ldflags_var)
EXTRA_ld_new_SOURCES = $(TARGETSOURCES)
incremental_dump_SOURCES = incremental-dump.cc
incremental_dump_DEPENDENCIES = $(TARGETOBJS) libgold.a $(LIBIBERTY) \
@@ -601,7 +613,7 @@ incremental-dump$(EXEEXT): $(incremental_dump_OBJECTS) $(incremental_dump_DEPEND
$(CXXLINK) $(incremental_dump_OBJECTS) $(incremental_dump_LDADD) $(LIBS)
ld-new$(EXEEXT): $(ld_new_OBJECTS) $(ld_new_DEPENDENCIES)
@rm -f ld-new$(EXEEXT)
- $(CXXLINK) $(ld_new_OBJECTS) $(ld_new_LDADD) $(LIBS)
+ $(ld_new_LINK) $(ld_new_OBJECTS) $(ld_new_LDADD) $(LIBS)
ld1$(EXEEXT): $(ld1_OBJECTS) $(ld1_DEPENDENCIES)
@rm -f ld1$(EXEEXT)
$(ld1_LINK) $(ld1_OBJECTS) $(ld1_LDADD) $(LIBS)
@@ -644,6 +656,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/expression.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileread.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gdb-index.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gold-threads.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gold.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/i386.Po@am__quote@
@@ -655,6 +668,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mapfile.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/merge.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nacl.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output.Po@am__quote@
diff --git a/binutils-2.22/gold/aclocal.m4 b/binutils-2.22/gold/aclocal.m4
index ded4d60..00cc0f8 100644
--- a/binutils-2.22/gold/aclocal.m4
+++ b/binutils-2.22/gold/aclocal.m4
@@ -982,6 +982,7 @@ AC_SUBST([am__untar])
m4_include([../config/depstand.m4])
m4_include([../config/gettext-sister.m4])
+m4_include([../config/lcmessage.m4])
m4_include([../config/lead-dot.m4])
m4_include([../config/nls.m4])
m4_include([../config/override.m4])
diff --git a/binutils-2.22/gold/archive.cc b/binutils-2.22/gold/archive.cc
index c2e6ff6..4db813d 100644
--- a/binutils-2.22/gold/archive.cc
+++ b/binutils-2.22/gold/archive.cc
@@ -104,6 +104,11 @@ Library_base::should_include_member(Symbol_table* symtab, Layout* layout,
*why = "-u ";
*why += sym_name;
}
+ else if (parameters->options().is_export_dynamic_symbol(sym_name))
+ {
+ *why = "--export-dynamic-symbol ";
+ *why += sym_name;
+ }
else if (layout->script_options()->is_referenced(sym_name))
{
size_t alc = 100 + strlen(sym_name);
diff --git a/binutils-2.22/gold/arm.cc b/binutils-2.22/gold/arm.cc
index 02b5a95..fa257a7 100644
--- a/binutils-2.22/gold/arm.cc
+++ b/binutils-2.22/gold/arm.cc
@@ -1,6 +1,6 @@
// arm.cc -- arm target support for gold.
-// Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
// Written by Doug Kwan <dougkwan@google.com> based on the i386 code
// by Ian Lance Taylor <iant@google.com>.
// This file also contains borrowed and adapted code from
@@ -51,6 +51,7 @@
#include "gc.h"
#include "attributes.h"
#include "arm-reloc-property.h"
+#include "nacl.h"
namespace
{
@@ -61,6 +62,9 @@ template<bool big_endian>
class Output_data_plt_arm;
template<bool big_endian>
+class Output_data_plt_arm_standard;
+
+template<bool big_endian>
class Stub_table;
template<bool big_endian>
@@ -107,7 +111,7 @@ const size_t ARM_TCB_SIZE = 8;
//
// This is a very simple port of gold for ARM-EABI. It is intended for
// supporting Android only for the time being.
-//
+//
// TODOs:
// - Implement all static relocation types documented in arm-reloc.def.
// - Make PLTs more flexible for different architecture features like
@@ -138,7 +142,7 @@ class Insn_template
enum Type
{
THUMB16_TYPE = 1,
- // THUMB16_SPECIAL_TYPE is used by sub-classes of Stub for instruction
+ // THUMB16_SPECIAL_TYPE is used by sub-classes of Stub for instruction
// templates with class-specific semantics. Currently this is used
// only by the Cortex_a8_stub class for handling condition codes in
// conditional branches.
@@ -152,24 +156,24 @@ class Insn_template
static const Insn_template
thumb16_insn(uint32_t data)
- { return Insn_template(data, THUMB16_TYPE, elfcpp::R_ARM_NONE, 0); }
+ { return Insn_template(data, THUMB16_TYPE, elfcpp::R_ARM_NONE, 0); }
// A Thumb conditional branch, in which the proper condition is inserted
// when we build the stub.
static const Insn_template
thumb16_bcond_insn(uint32_t data)
- { return Insn_template(data, THUMB16_SPECIAL_TYPE, elfcpp::R_ARM_NONE, 1); }
+ { return Insn_template(data, THUMB16_SPECIAL_TYPE, elfcpp::R_ARM_NONE, 1); }
static const Insn_template
thumb32_insn(uint32_t data)
- { return Insn_template(data, THUMB32_TYPE, elfcpp::R_ARM_NONE, 0); }
+ { return Insn_template(data, THUMB32_TYPE, elfcpp::R_ARM_NONE, 0); }
static const Insn_template
thumb32_b_insn(uint32_t data, int reloc_addend)
{
return Insn_template(data, THUMB32_TYPE, elfcpp::R_ARM_THM_JUMP24,
reloc_addend);
- }
+ }
static const Insn_template
arm_insn(uint32_t data)
@@ -181,7 +185,7 @@ class Insn_template
static const Insn_template
data_word(unsigned data, unsigned int r_type, int reloc_addend)
- { return Insn_template(data, DATA_TYPE, r_type, reloc_addend); }
+ { return Insn_template(data, DATA_TYPE, r_type, reloc_addend); }
// Accessors. This class is used for read-only objects so no modifiers
// are provided.
@@ -270,7 +274,7 @@ typedef enum
arm_stub_cortex_a8_first = arm_stub_a8_veneer_b_cond,
// Last Cortex-A8 stub type.
arm_stub_cortex_a8_last = arm_stub_a8_veneer_blx,
-
+
// Last stub type.
arm_stub_type_last = arm_stub_v4_veneer_bx
} Stub_type;
@@ -312,7 +316,7 @@ class Stub_template
unsigned
alignment() const
{ return this->alignment_; }
-
+
// Return whether entry point is in thumb mode.
bool
entry_in_thumb_mode() const
@@ -349,7 +353,7 @@ class Stub_template
// as possible.
Stub_template(const Stub_template&);
Stub_template& operator=(const Stub_template&);
-
+
// Stub type.
Stub_type type_;
// Points to an array of Insn_templates.
@@ -364,7 +368,7 @@ class Stub_template
bool entry_in_thumb_mode_;
// A table of reloc instruction indices and offsets. We can find these by
// looking at the instruction templates but we pre-compute and then stash
- // them here for speed.
+ // them here for speed.
std::vector<Reloc> relocs_;
};
@@ -405,7 +409,7 @@ class Stub
void
set_offset(section_offset_type offset)
{ this->offset_ = offset; }
-
+
// Return the relocation target address of the i-th relocation in the
// stub. This must be defined in a child class.
Arm_address
@@ -437,7 +441,7 @@ class Stub
else
this->do_fixed_endian_write<false>(view, view_size);
}
-
+
// This must be overridden if a child class uses the THUMB16_SPECIAL_TYPE
// instruction template.
virtual uint16_t
@@ -550,7 +554,7 @@ class Reloc_stub : public Stub
// Whether this equals to another key k.
bool
- eq(const Key& k) const
+ eq(const Key& k) const
{
return ((this->stub_type_ == k.stub_type_)
&& (this->r_sym_ == k.r_sym_)
@@ -600,7 +604,7 @@ class Reloc_stub : public Stub
unsigned int r_sym_;
// If r_sym_ is an invalid index, this points to a global symbol.
// Otherwise, it points to a relobj. We used the unsized and target
- // independent Symbol and Relobj classes instead of Sized_symbol<32> and
+ // independent Symbol and Relobj classes instead of Sized_symbol<32> and
// Arm_relobj, in order to avoid making the stub class a template
// as most of the stub machinery is endianness-neutral. However, it
// may require a bit of casting done by users of this class.
@@ -641,7 +645,7 @@ class Reloc_stub : public Stub
// Cortex-A8 stub class. We need a Cortex-A8 stub to redirect any 32-bit
// THUMB branch that meets the following conditions:
-//
+//
// 1. The branch straddles across a page boundary. i.e. lower 12-bit of
// branch address is 0xffe.
// 2. The branch target address is in the same page as the first word of the
@@ -715,15 +719,15 @@ class Cortex_a8_stub : public Stub
{
if (this->stub_template()->type() == arm_stub_a8_veneer_b_cond)
{
- // The conditional branch veneer has two relocations.
- gold_assert(i < 2);
+ // The conditional branch veneer has two relocations.
+ gold_assert(i < 2);
return i == 0 ? this->source_address_ + 4 : this->destination_address_;
}
else
{
- // All other Cortex-A8 stubs have only one relocation.
- gold_assert(i == 0);
- return this->destination_address_;
+ // All other Cortex-A8 stubs have only one relocation.
+ gold_assert(i == 0);
+ return this->destination_address_;
}
}
@@ -850,13 +854,13 @@ class Stub_factory
private:
// Constructor and destructor are protected since we only return a single
// instance created in Stub_factory::get_instance().
-
+
Stub_factory();
// A Stub_factory may not be copied since it is a singleton.
Stub_factory(const Stub_factory&);
Stub_factory& operator=(Stub_factory&);
-
+
// Stub templates. These are initialized in the constructor.
const Stub_template* stub_templates_[arm_stub_type_last+1];
};
@@ -970,7 +974,7 @@ class Stub_table : public Output_data
// needing the Cortex-A8 workaround.
void
finalize_stubs();
-
+
// Apply Cortex-A8 workaround to an address range.
void
apply_cortex_a8_workaround_to_address_range(Target_arm<big_endian>*,
@@ -981,7 +985,7 @@ class Stub_table : public Output_data
// Write out section contents.
void
do_write(Output_file*);
-
+
// Return the required alignment.
uint64_t
do_addralign() const
@@ -996,7 +1000,7 @@ class Stub_table : public Output_data
void
set_final_data_size()
{ this->set_data_size(this->current_data_size()); }
-
+
private:
// Relocate one stub.
void
@@ -1074,7 +1078,7 @@ class Arm_exidx_cantunwind : public Output_section_data
template<bool big_endian>
void inline
do_fixed_endian_write(Output_file*);
-
+
// The object containing the section pointed by this.
Relobj* relobj_;
// The section index of the section pointed by this.
@@ -1083,7 +1087,7 @@ class Arm_exidx_cantunwind : public Output_section_data
// During EXIDX coverage fix-up, we compact an EXIDX section. The
// Offset map is used to map input section offset within the EXIDX section
-// to the output offset from the start of this EXIDX section.
+// to the output offset from the start of this EXIDX section.
typedef std::map<section_offset_type, section_offset_type>
Arm_exidx_section_offset_map;
@@ -1132,7 +1136,7 @@ class Arm_exidx_merged_section : public Output_relaxed_input_section
const Arm_exidx_input_section& exidx_input_section_;
// Section offset map.
const Arm_exidx_section_offset_map& section_offset_map_;
- // Merged section contents. We need to keep build the merged section
+ // Merged section contents. We need to keep build the merged section
// and save it here to avoid accessing the original EXIDX section when
// we cannot lock the sections' object.
unsigned char* section_contents_;
@@ -1156,7 +1160,7 @@ class Arm_input_section : public Output_relaxed_input_section
// Initialize.
void
init();
-
+
// Whether this is a stub table owner.
bool
is_stub_table_owner() const
@@ -1211,7 +1215,7 @@ class Arm_input_section : public Output_relaxed_input_section
bool
do_output_offset(const Relobj* object, unsigned int shndx,
section_offset_type offset,
- section_offset_type* poutput) const
+ section_offset_type* poutput) const
{
if ((object == this->relobj())
&& (shndx == this->shndx())
@@ -1272,7 +1276,7 @@ class Arm_exidx_fixup
const unsigned char* section_contents,
section_size_type section_size,
Arm_exidx_section_offset_map** psection_offset_map);
-
+
// Append an EXIDX_CANTUNWIND entry pointing at the end of the last
// input section, if there is not one already.
void
@@ -1356,7 +1360,7 @@ class Arm_output_section : public Output_section
~Arm_output_section()
{ }
-
+
// Group input sections for stub generation.
void
group_sections(section_size_type, bool, Target_arm<big_endian>*, const Task*);
@@ -1416,7 +1420,7 @@ class Arm_exidx_input_section
~Arm_exidx_input_section()
{ }
-
+
// Accessors: This is a read-only class.
// Return the object containing this EXIDX input section.
@@ -1485,7 +1489,7 @@ class Arm_relobj : public Sized_relobj_file<32, big_endian>
static const Arm_address invalid_address = static_cast<Arm_address>(-1);
Arm_relobj(const std::string& name, Input_file* input_file, off_t offset,
- const typename elfcpp::Ehdr<32, big_endian>& ehdr)
+ const typename elfcpp::Ehdr<32, big_endian>& ehdr)
: Sized_relobj_file<32, big_endian>(name, input_file, offset, ehdr),
stub_tables_(), local_symbol_is_thumb_function_(),
attributes_section_data_(NULL), mapping_symbols_info_(),
@@ -1496,7 +1500,7 @@ class Arm_relobj : public Sized_relobj_file<32, big_endian>
~Arm_relobj()
{ delete this->attributes_section_data_; }
-
+
// Return the stub table of the SHNDX-th section if there is one.
Stub_table<big_endian>*
stub_table(unsigned int shndx) const
@@ -1521,7 +1525,7 @@ class Arm_relobj : public Sized_relobj_file<32, big_endian>
gold_assert(r_sym < this->local_symbol_is_thumb_function_.size());
return this->local_symbol_is_thumb_function_[r_sym];
}
-
+
// Scan all relocation sections for stub generation.
void
scan_sections_for_stubs(Target_arm<big_endian>*, const Symbol_table*,
@@ -1569,7 +1573,7 @@ class Arm_relobj : public Sized_relobj_file<32, big_endian>
|| (p1.first == p2.first && p1.second < p2.second));
}
};
-
+
// We only care about the first character of a mapping symbol, so
// we only store that instead of the whole symbol name.
typedef std::map<Mapping_symbol_position, char,
@@ -1578,11 +1582,11 @@ class Arm_relobj : public Sized_relobj_file<32, big_endian>
// Whether a section contains any Cortex-A8 workaround.
bool
section_has_cortex_a8_workaround(unsigned int shndx) const
- {
+ {
return (this->section_has_cortex_a8_workaround_ != NULL
&& (*this->section_has_cortex_a8_workaround_)[shndx]);
}
-
+
// Mark a section that has Cortex-A8 workaround.
void
mark_section_for_cortex_a8_workaround(unsigned int shndx)
@@ -1625,7 +1629,7 @@ class Arm_relobj : public Sized_relobj_file<32, big_endian>
void
set_output_local_symbol_count_needs_update()
{ this->output_local_symbol_count_needs_update_ = true; }
-
+
// Update output local symbol count at the end of relaxation.
void
update_output_local_symbol_count();
@@ -1634,7 +1638,7 @@ class Arm_relobj : public Sized_relobj_file<32, big_endian>
bool
merge_flags_and_attributes() const
{ return this->merge_flags_and_attributes_; }
-
+
// Export list of EXIDX section indices.
void
get_exidx_shndx_list(std::vector<unsigned int>* list) const
@@ -1647,7 +1651,7 @@ class Arm_relobj : public Sized_relobj_file<32, big_endian>
if (p->second->shndx() == p->first)
list->push_back(p->first);
}
- // Sort list to make result independent of implementation of map.
+ // Sort list to make result independent of implementation of map.
std::sort(list->begin(), list->end());
}
@@ -1667,7 +1671,7 @@ class Arm_relobj : public Sized_relobj_file<32, big_endian>
// Count the local symbols.
void
do_count_local_symbols(Stringpool_template<char>*,
- Stringpool_template<char>*);
+ Stringpool_template<char>*);
void
do_relocate_sections(
@@ -1769,7 +1773,7 @@ class Arm_dynobj : public Sized_dynobj<32, big_endian>
: Sized_dynobj<32, big_endian>(name, input_file, offset, ehdr),
processor_specific_flags_(0), attributes_section_data_(NULL)
{ }
-
+
~Arm_dynobj()
{ delete this->attributes_section_data_; }
@@ -1862,13 +1866,13 @@ class Cortex_a8_reloc
{ }
// Accessors: This is a read-only class.
-
+
// Return the relocation stub associated with this relocation if there is
// one.
const Reloc_stub*
reloc_stub() const
- { return this->reloc_stub_; }
-
+ { return this->reloc_stub_; }
+
// Return the relocation type.
unsigned int
r_type() const
@@ -2076,7 +2080,7 @@ class Arm_scan_relocatable_relocs :
case elfcpp::R_ARM_TARGET2:
gold_unreachable();
// Relocations that write full 32 bits and
- // have alignment of 1.
+ // have alignment of 1.
case elfcpp::R_ARM_ABS32:
case elfcpp::R_ARM_REL32:
case elfcpp::R_ARM_SBREL32:
@@ -2103,65 +2107,6 @@ class Arm_scan_relocatable_relocs :
}
};
-// Utilities for manipulating integers of up to 32-bits
-
-namespace utils
-{
- // Sign extend an n-bit unsigned integer stored in an uint32_t into
- // an int32_t. NO_BITS must be between 1 to 32.
- template<int no_bits>
- static inline int32_t
- sign_extend(uint32_t bits)
- {
- gold_assert(no_bits >= 0 && no_bits <= 32);
- if (no_bits == 32)
- return static_cast<int32_t>(bits);
- uint32_t mask = (~((uint32_t) 0)) >> (32 - no_bits);
- bits &= mask;
- uint32_t top_bit = 1U << (no_bits - 1);
- int32_t as_signed = static_cast<int32_t>(bits);
- return (bits & top_bit) ? as_signed + (-top_bit * 2) : as_signed;
- }
-
- // Detects overflow of an NO_BITS integer stored in a uint32_t.
- template<int no_bits>
- static inline bool
- has_overflow(uint32_t bits)
- {
- gold_assert(no_bits >= 0 && no_bits <= 32);
- if (no_bits == 32)
- return false;
- int32_t max = (1 << (no_bits - 1)) - 1;
- int32_t min = -(1 << (no_bits - 1));
- int32_t as_signed = static_cast<int32_t>(bits);
- return as_signed > max || as_signed < min;
- }
-
- // Detects overflow of an NO_BITS integer stored in a uint32_t when it
- // fits in the given number of bits as either a signed or unsigned value.
- // For example, has_signed_unsigned_overflow<8> would check
- // -128 <= bits <= 255
- template<int no_bits>
- static inline bool
- has_signed_unsigned_overflow(uint32_t bits)
- {
- gold_assert(no_bits >= 2 && no_bits <= 32);
- if (no_bits == 32)
- return false;
- int32_t max = static_cast<int32_t>((1U << no_bits) - 1);
- int32_t min = -(1 << (no_bits - 1));
- int32_t as_signed = static_cast<int32_t>(bits);
- return as_signed > max || as_signed < min;
- }
-
- // Select bits from A and B using bits in MASK. For each n in [0..31],
- // the n-th bit in the result is chosen from the n-th bits of A and B.
- // A zero selects A and a one selects B.
- static inline uint32_t
- bit_select(uint32_t a, uint32_t b, uint32_t mask)
- { return (a & ~mask) | (b & mask); }
-};
-
template<bool big_endian>
class Target_arm : public Sized_target<32, big_endian>
{
@@ -2172,10 +2117,10 @@ class Target_arm : public Sized_target<32, big_endian>
// When were are relocating a stub, we pass this as the relocation number.
static const size_t fake_relnum_for_stubs = static_cast<size_t>(-1);
- Target_arm()
- : Sized_target<32, big_endian>(&arm_info),
+ Target_arm(const Target::Target_info* info = &arm_info)
+ : Sized_target<32, big_endian>(info),
got_(NULL), plt_(NULL), got_plt_(NULL), rel_dyn_(NULL),
- copy_relocs_(elfcpp::R_ARM_COPY), dynbss_(NULL),
+ copy_relocs_(elfcpp::R_ARM_COPY), dynbss_(NULL),
got_mod_index_offset_(-1U), tls_base_symbol_defined_(false),
stub_tables_(), stub_factory_(Stub_factory::get_instance()),
should_force_pic_veneer_(false),
@@ -2192,7 +2137,7 @@ class Target_arm : public Sized_target<32, big_endian>
void
set_should_force_pic_veneer(bool value)
{ this->should_force_pic_veneer_ = value; }
-
+
// Whether we use THUMB-2 instructions.
bool
using_thumb2() const
@@ -2255,7 +2200,7 @@ class Target_arm : public Sized_target<32, big_endian>
return (arch != elfcpp::TAG_CPU_ARCH_PRE_V4
&& arch != elfcpp::TAG_CPU_ARCH_V4);
}
-
+
// Whether we have v5T interworking instructions available.
bool
may_use_v5t_interworking() const
@@ -2274,8 +2219,8 @@ class Target_arm : public Sized_target<32, big_endian>
&& arch != elfcpp::TAG_CPU_ARCH_V4
&& arch != elfcpp::TAG_CPU_ARCH_V4T);
}
-
- // Process the relocations to determine unreferenced sections for
+
+ // Process the relocations to determine unreferenced sections for
// garbage collection.
void
gc_process_relocs(Symbol_table* symtab,
@@ -2370,10 +2315,10 @@ class Target_arm : public Sized_target<32, big_endian>
view_address,
section_size_type view_size,
unsigned char* preloc_out);
-
+
// Return whether SYM is defined by the ABI.
bool
- do_is_defined_by_abi(Symbol* sym) const
+ do_is_defined_by_abi(const Symbol* sym) const
{ return strcmp(sym->name(), "__tls_get_addr") == 0; }
// Return whether there is a GOT section.
@@ -2417,7 +2362,7 @@ class Target_arm : public Sized_target<32, big_endian>
//
// Methods to support stub-generations.
//
-
+
// Return the stub factory
const Stub_factory&
stub_factory() const
@@ -2443,12 +2388,12 @@ class Target_arm : public Sized_target<32, big_endian>
bool, const unsigned char*, Arm_address,
section_size_type);
- // Relocate a stub.
+ // Relocate a stub.
void
relocate_stub(Stub*, const Relocate_info<32, big_endian>*,
Output_section*, unsigned char*, Arm_address,
section_size_type);
-
+
// Get the default ARM target.
static Target_arm<big_endian>*
default_target()
@@ -2499,6 +2444,11 @@ class Target_arm : public Sized_target<32, big_endian>
unsigned char*, Arm_address);
protected:
+ // Make the PLT-generator object.
+ Output_data_plt_arm<big_endian>*
+ make_data_plt(Layout* layout, Output_data_space* got_plt)
+ { return this->do_make_data_plt(layout, got_plt); }
+
// Make an ELF object.
Object*
do_make_elf_object(const std::string&, Input_file*, off_t,
@@ -2573,10 +2523,16 @@ class Target_arm : public Sized_target<32, big_endian>
&& !is_prefix_of(".ARM.extab", section_name)
&& Target::do_section_may_have_icf_unsafe_pointers(section_name));
}
-
+
virtual void
do_define_standard_symbols(Symbol_table*, Layout*);
+ virtual Output_data_plt_arm<big_endian>*
+ do_make_data_plt(Layout* layout, Output_data_space* got_plt)
+ {
+ return new Output_data_plt_arm_standard<big_endian>(layout, got_plt);
+ }
+
private:
// The class which scans relocations.
class Scan
@@ -2607,19 +2563,19 @@ class Target_arm : public Sized_target<32, big_endian>
inline bool
local_reloc_may_be_function_pointer(Symbol_table* , Layout* , Target_arm* ,
- Sized_relobj_file<32, big_endian>* ,
- unsigned int ,
- Output_section* ,
- const elfcpp::Rel<32, big_endian>& ,
+ Sized_relobj_file<32, big_endian>* ,
unsigned int ,
- const elfcpp::Sym<32, big_endian>&);
+ Output_section* ,
+ const elfcpp::Rel<32, big_endian>& ,
+ unsigned int ,
+ const elfcpp::Sym<32, big_endian>&);
inline bool
global_reloc_may_be_function_pointer(Symbol_table* , Layout* , Target_arm* ,
- Sized_relobj_file<32, big_endian>* ,
- unsigned int ,
- Output_section* ,
- const elfcpp::Rel<32, big_endian>& ,
+ Sized_relobj_file<32, big_endian>* ,
+ unsigned int ,
+ Output_section* ,
+ const elfcpp::Rel<32, big_endian>& ,
unsigned int , Symbol*);
private:
@@ -2726,7 +2682,7 @@ class Target_arm : public Sized_target<32, big_endian>
// Do a TLS relocation.
inline typename Arm_relocate_functions<big_endian>::Status
relocate_tls(const Relocate_info<32, big_endian>*, Target_arm<big_endian>*,
- size_t, const elfcpp::Rel<32, big_endian>&, unsigned int,
+ size_t, const elfcpp::Rel<32, big_endian>&, unsigned int,
const Sized_symbol<32>*, const Symbol_value<32>*,
unsigned char*, elfcpp::Elf_types<32>::Elf_Addr,
section_size_type);
@@ -2921,7 +2877,7 @@ class Target_arm : public Sized_target<32, big_endian>
Arm_input_section<big_endian>*,
Section_id_hash>
Arm_input_section_map;
-
+
// Map output addresses to relocs for Cortex-A8 erratum.
typedef Unordered_map<Arm_address, const Cortex_a8_reloc*>
Cortex_a8_relocs_info;
@@ -2974,6 +2930,8 @@ const Target::Target_info Target_arm<big_endian>::arm_info =
0x8000, // default_text_segment_address
0x1000, // abi_pagesize (overridable by -z max-page-size)
0x1000, // common_pagesize (overridable by -z common-page-size)
+ false, // isolate_execinstr
+ 0, // rosegment_gap
elfcpp::SHN_UNDEF, // small_common_shndx
elfcpp::SHN_UNDEF, // large_common_shndx
0, // small_common_section_flags
@@ -3002,10 +2960,10 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
// Encoding of imm16 argument for movt and movw ARM instructions
// from ARM ARM:
- //
+ //
// imm16 := imm4 | imm12
//
- // f e d c b a 9 8 7 6 5 4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0
+ // f e d c b a 9 8 7 6 5 4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0
// +-------+---------------+-------+-------+-----------------------+
// | | |imm4 | |imm12 |
// +-------+---------------+-------+-------+-----------------------+
@@ -3018,7 +2976,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
{
// According to the Elf ABI for ARM Architecture the immediate
// field is sign-extended to form the addend.
- return utils::sign_extend<16>(((val >> 4) & 0xf000) | (val & 0xfff));
+ return Bits<16>::sign_extend32(((val >> 4) & 0xf000) | (val & 0xfff));
}
// Insert X into VAL based on the ARM instruction encoding described
@@ -3036,10 +2994,10 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
// Encoding of imm16 argument for movt and movw Thumb2 instructions
// from ARM ARM:
- //
+ //
// imm16 := imm4 | i | imm3 | imm8
//
- // f e d c b a 9 8 7 6 5 4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0
+ // f e d c b a 9 8 7 6 5 4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0
// +---------+-+-----------+-------++-+-----+-------+---------------+
// | |i| |imm4 || |imm3 | |imm8 |
// +---------+-+-----------+-------++-+-----+-------+---------------+
@@ -3052,10 +3010,10 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
{
// According to the Elf ABI for ARM Architecture the immediate
// field is sign-extended to form the addend.
- return utils::sign_extend<16>(((val >> 4) & 0xf000)
- | ((val >> 15) & 0x0800)
- | ((val >> 4) & 0x0700)
- | (val & 0x00ff));
+ return Bits<16>::sign_extend32(((val >> 4) & 0xf000)
+ | ((val >> 15) & 0x0800)
+ | ((val >> 4) & 0x0700)
+ | (val & 0x00ff));
}
// Insert X into VAL based on the Thumb2 instruction encoding
@@ -3163,8 +3121,8 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
uint32_t i1 = j1 ^ s ? 0 : 1;
uint32_t i2 = j2 ^ s ? 0 : 1;
- return utils::sign_extend<25>((s << 24) | (i1 << 23) | (i2 << 22)
- | (upper << 12) | (lower << 1));
+ return Bits<25>::sign_extend32((s << 24) | (i1 << 23) | (i2 << 22)
+ | (upper << 12) | (lower << 1));
}
// Insert OFFSET to a 32-bit THUMB branch and return the upper instruction.
@@ -3187,9 +3145,9 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
uint32_t s = offset < 0 ? 1 : 0;
uint32_t bits = static_cast<uint32_t>(offset);
return ((lower_insn & ~0x2fffU)
- | ((((bits >> 23) & 1) ^ !s) << 13)
- | ((((bits >> 22) & 1) ^ !s) << 11)
- | ((bits >> 1) & 0x7ffU));
+ | ((((bits >> 23) & 1) ^ !s) << 13)
+ | ((((bits >> 22) & 1) ^ !s) << 11)
+ | ((bits >> 1) & 0x7ffU));
}
// Return the branch offset of a 32-bit THUMB conditional branch.
@@ -3202,7 +3160,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
uint32_t lower = (lower_insn & 0x07ffU);
uint32_t upper = (s << 8) | (j2 << 7) | (j1 << 6) | (upper_insn & 0x003fU);
- return utils::sign_extend<21>((upper << 12) | (lower << 1));
+ return Bits<21>::sign_extend32((upper << 12) | (lower << 1));
}
// Insert OFFSET to a 32-bit THUMB conditional branch and return the upper
@@ -3239,14 +3197,13 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
typedef typename elfcpp::Swap<8, big_endian>::Valtype Valtype;
Valtype* wv = reinterpret_cast<Valtype*>(view);
Valtype val = elfcpp::Swap<8, big_endian>::readval(wv);
- int32_t addend = utils::sign_extend<8>(val);
+ int32_t addend = Bits<8>::sign_extend32(val);
Arm_address x = psymval->value(object, addend);
- val = utils::bit_select(val, x, 0xffU);
+ val = Bits<32>::bit_select32(val, x, 0xffU);
elfcpp::Swap<8, big_endian>::writeval(wv, val);
// R_ARM_ABS8 permits signed or unsigned results.
- int signed_x = static_cast<int32_t>(x);
- return ((signed_x < -128 || signed_x > 255)
+ return (Bits<8>::has_signed_unsigned_overflow32(x)
? This::STATUS_OVERFLOW
: This::STATUS_OKAY);
}
@@ -3263,12 +3220,9 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
Valtype val = elfcpp::Swap<16, big_endian>::readval(wv);
Reltype addend = (val & 0x7e0U) >> 6;
Reltype x = psymval->value(object, addend);
- val = utils::bit_select(val, x << 6, 0x7e0U);
+ val = Bits<32>::bit_select32(val, x << 6, 0x7e0U);
elfcpp::Swap<16, big_endian>::writeval(wv, val);
-
- // R_ARM_ABS16 permits signed or unsigned results.
- int signed_x = static_cast<int32_t>(x);
- return ((signed_x < -32768 || signed_x > 65535)
+ return (Bits<5>::has_overflow32(x)
? This::STATUS_OVERFLOW
: This::STATUS_OKAY);
}
@@ -3285,9 +3239,9 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
Reltype addend = val & 0x0fffU;
Reltype x = psymval->value(object, addend);
- val = utils::bit_select(val, x, 0x0fffU);
+ val = Bits<32>::bit_select32(val, x, 0x0fffU);
elfcpp::Swap<32, big_endian>::writeval(wv, val);
- return (utils::has_overflow<12>(x)
+ return (Bits<12>::has_overflow32(x)
? This::STATUS_OVERFLOW
: This::STATUS_OKAY);
}
@@ -3299,16 +3253,14 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
const Symbol_value<32>* psymval)
{
typedef typename elfcpp::Swap_unaligned<16, big_endian>::Valtype Valtype;
- typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype;
Valtype val = elfcpp::Swap_unaligned<16, big_endian>::readval(view);
- int32_t addend = utils::sign_extend<16>(val);
+ int32_t addend = Bits<16>::sign_extend32(val);
Arm_address x = psymval->value(object, addend);
- val = utils::bit_select(val, x, 0xffffU);
+ val = Bits<32>::bit_select32(val, x, 0xffffU);
elfcpp::Swap_unaligned<16, big_endian>::writeval(view, val);
// R_ARM_ABS16 permits signed or unsigned results.
- int signed_x = static_cast<int32_t>(x);
- return ((signed_x < -32768 || signed_x > 65536)
+ return (Bits<16>::has_signed_unsigned_overflow32(x)
? This::STATUS_OVERFLOW
: This::STATUS_OKAY);
}
@@ -3380,12 +3332,12 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype;
Valtype* wv = reinterpret_cast<Valtype*>(view);
Valtype val = elfcpp::Swap<16, big_endian>::readval(wv);
- int32_t addend = utils::sign_extend<8>((val & 0x00ff) << 1);
+ int32_t addend = Bits<8>::sign_extend32((val & 0x00ff) << 1);
int32_t x = (psymval->value(object, addend) - address);
elfcpp::Swap<16, big_endian>::writeval(wv, ((val & 0xff00)
- | ((x & 0x01fe) >> 1)));
+ | ((x & 0x01fe) >> 1)));
// We do a 9-bit overflow check because x is right-shifted by 1 bit.
- return (utils::has_overflow<9>(x)
+ return (Bits<9>::has_overflow32(x)
? This::STATUS_OVERFLOW
: This::STATUS_OKAY);
}
@@ -3400,12 +3352,12 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype;
Valtype* wv = reinterpret_cast<Valtype*>(view);
Valtype val = elfcpp::Swap<16, big_endian>::readval(wv);
- int32_t addend = utils::sign_extend<11>((val & 0x07ff) << 1);
+ int32_t addend = Bits<11>::sign_extend32((val & 0x07ff) << 1);
int32_t x = (psymval->value(object, addend) - address);
elfcpp::Swap<16, big_endian>::writeval(wv, ((val & 0xf800)
- | ((x & 0x0ffe) >> 1)));
+ | ((x & 0x0ffe) >> 1)));
// We do a 12-bit overflow check because x is right-shifted by 1 bit.
- return (utils::has_overflow<12>(x)
+ return (Bits<12>::has_overflow32(x)
? This::STATUS_OVERFLOW
: This::STATUS_OKAY);
}
@@ -3458,12 +3410,13 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
{
typedef typename elfcpp::Swap_unaligned<32, big_endian>::Valtype Valtype;
Valtype val = elfcpp::Swap_unaligned<32, big_endian>::readval(view);
- Valtype addend = utils::sign_extend<31>(val);
+ Valtype addend = Bits<31>::sign_extend32(val);
Valtype x = (psymval->value(object, addend) | thumb_bit) - address;
- val = utils::bit_select(val, x, 0x7fffffffU);
+ val = Bits<32>::bit_select32(val, x, 0x7fffffffU);
elfcpp::Swap_unaligned<32, big_endian>::writeval(view, val);
- return (utils::has_overflow<31>(x) ?
- This::STATUS_OVERFLOW : This::STATUS_OKAY);
+ return (Bits<31>::has_overflow32(x)
+ ? This::STATUS_OVERFLOW
+ : This::STATUS_OKAY);
}
// R_ARM_MOVW_ABS_NC: (S + A) | T (relative address base is )
@@ -3486,7 +3439,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
- relative_address_base);
val = This::insert_val_arm_movw_movt(val, x);
elfcpp::Swap<32, big_endian>::writeval(wv, val);
- return ((check_overflow && utils::has_overflow<16>(x))
+ return ((check_overflow && Bits<16>::has_overflow32(x))
? This::STATUS_OVERFLOW
: This::STATUS_OKAY);
}
@@ -3534,8 +3487,8 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
val = This::insert_val_thumb_movw_movt(val, x);
elfcpp::Swap<16, big_endian>::writeval(wv, val >> 16);
elfcpp::Swap<16, big_endian>::writeval(wv + 1, val & 0xffff);
- return ((check_overflow && utils::has_overflow<16>(x))
- ? This::STATUS_OVERFLOW
+ return ((check_overflow && Bits<16>::has_overflow32(x))
+ ? This::STATUS_OVERFLOW
: This::STATUS_OKAY);
}
@@ -3612,7 +3565,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
elfcpp::Swap<16, big_endian>::writeval(wv, insn >> 16);
elfcpp::Swap<16, big_endian>::writeval(wv + 1, insn & 0xffff);
return ((val > 0xfff) ?
- This::STATUS_OVERFLOW : This::STATUS_OKAY);
+ This::STATUS_OVERFLOW : This::STATUS_OKAY);
}
// R_ARM_THM_PC8: S + A - Pa (Thumb)
@@ -3667,7 +3620,7 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
elfcpp::Swap<16, big_endian>::writeval(wv, insn >> 16);
elfcpp::Swap<16, big_endian>::writeval(wv + 1, insn & 0xffff);
return ((val > 0xfff) ?
- This::STATUS_OVERFLOW : This::STATUS_OKAY);
+ This::STATUS_OVERFLOW : This::STATUS_OKAY);
}
// R_ARM_V4BX
@@ -3912,9 +3865,9 @@ Arm_relocate_functions<big_endian>::arm_branch_common(
typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
Valtype* wv = reinterpret_cast<Valtype*>(view);
Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
-
+
bool insn_is_b = (((val >> 28) & 0xf) <= 0xe)
- && ((val & 0x0f000000UL) == 0x0a000000UL);
+ && ((val & 0x0f000000UL) == 0x0a000000UL);
bool insn_is_uncond_bl = (val & 0xff000000UL) == 0xeb000000UL;
bool insn_is_cond_bl = (((val >> 28) & 0xf) < 0xe)
&& ((val & 0x0f000000UL) == 0x0b000000UL);
@@ -3965,8 +3918,8 @@ Arm_relocate_functions<big_endian>::arm_branch_common(
elfcpp::Swap<32, big_endian>::writeval(wv, val);
return This::STATUS_OKAY;
}
-
- Valtype addend = utils::sign_extend<26>(val << 2);
+
+ Valtype addend = Bits<26>::sign_extend32(val << 2);
Valtype branch_target = psymval->value(object, addend);
int32_t branch_offset = branch_target - address;
@@ -3976,7 +3929,7 @@ Arm_relocate_functions<big_endian>::arm_branch_common(
Reloc_stub* stub = NULL;
if (!parameters->options().relocatable()
- && (utils::has_overflow<26>(branch_offset)
+ && (Bits<26>::has_overflow32(branch_offset)
|| ((thumb_bit != 0)
&& !(may_use_blx && r_type == elfcpp::R_ARM_CALL))))
{
@@ -3998,7 +3951,7 @@ Arm_relocate_functions<big_endian>::arm_branch_common(
thumb_bit = stub->stub_template()->entry_in_thumb_mode() ? 1 : 0;
branch_target = stub_table->address() + stub->offset() + addend;
branch_offset = branch_target - address;
- gold_assert(!utils::has_overflow<26>(branch_offset));
+ gold_assert(!Bits<26>::has_overflow32(branch_offset));
}
}
@@ -4011,10 +3964,11 @@ Arm_relocate_functions<big_endian>::arm_branch_common(
val = (val & 0xffffff) | 0xfa000000 | ((branch_offset & 2) << 23);
}
- val = utils::bit_select(val, (branch_offset >> 2), 0xffffffUL);
+ val = Bits<32>::bit_select32(val, (branch_offset >> 2), 0xffffffUL);
elfcpp::Swap<32, big_endian>::writeval(wv, val);
- return (utils::has_overflow<26>(branch_offset)
- ? This::STATUS_OVERFLOW : This::STATUS_OKAY);
+ return (Bits<26>::has_overflow32(branch_offset)
+ ? This::STATUS_OVERFLOW
+ : This::STATUS_OKAY);
}
// Relocate THUMB long branches. This handles relocation types
@@ -4046,7 +4000,7 @@ Arm_relocate_functions<big_endian>::thumb_branch_common(
// into account.
bool is_bl_insn = (lower_insn & 0x1000U) == 0x1000U;
bool is_blx_insn = (lower_insn & 0x1000U) == 0x0000U;
-
+
// Check that the instruction is valid.
if (r_type == elfcpp::R_ARM_THM_CALL)
{
@@ -4069,7 +4023,7 @@ Arm_relocate_functions<big_endian>::thumb_branch_common(
gold_warning(_("%s: Thumb BLX instruction targets "
"thumb function '%s'."),
object->name().c_str(),
- (gsym ? gsym->name() : "(local)"));
+ (gsym ? gsym->name() : "(local)"));
// Convert BLX to BL.
lower_insn |= 0x1000U;
}
@@ -4098,14 +4052,14 @@ Arm_relocate_functions<big_endian>::thumb_branch_common(
}
return This::STATUS_OKAY;
}
-
+
int32_t addend = This::thumb32_branch_offset(upper_insn, lower_insn);
Arm_address branch_target = psymval->value(object, addend);
// For BLX, bit 1 of target address comes from bit 1 of base address.
bool may_use_blx = arm_target->may_use_v5t_interworking();
if (thumb_bit == 0 && may_use_blx)
- branch_target = utils::bit_select(branch_target, address, 0x2);
+ branch_target = Bits<32>::bit_select32(branch_target, address, 0x2);
int32_t branch_offset = branch_target - address;
@@ -4113,8 +4067,8 @@ Arm_relocate_functions<big_endian>::thumb_branch_common(
// to switch mode.
bool thumb2 = arm_target->using_thumb2();
if (!parameters->options().relocatable()
- && ((!thumb2 && utils::has_overflow<23>(branch_offset))
- || (thumb2 && utils::has_overflow<25>(branch_offset))
+ && ((!thumb2 && Bits<23>::has_overflow32(branch_offset))
+ || (thumb2 && Bits<25>::has_overflow32(branch_offset))
|| ((thumb_bit == 0)
&& (((r_type == elfcpp::R_ARM_THM_CALL) && !may_use_blx)
|| r_type == elfcpp::R_ARM_THM_JUMP24))))
@@ -4137,8 +4091,8 @@ Arm_relocate_functions<big_endian>::thumb_branch_common(
gold_assert(stub != NULL);
thumb_bit = stub->stub_template()->entry_in_thumb_mode() ? 1 : 0;
branch_target = stub_table->address() + stub->offset() + addend;
- if (thumb_bit == 0 && may_use_blx)
- branch_target = utils::bit_select(branch_target, address, 0x2);
+ if (thumb_bit == 0 && may_use_blx)
+ branch_target = Bits<32>::bit_select32(branch_target, address, 0x2);
branch_offset = branch_target - address;
}
}
@@ -4175,11 +4129,11 @@ Arm_relocate_functions<big_endian>::thumb_branch_common(
elfcpp::Swap<16, big_endian>::writeval(wv, upper_insn);
elfcpp::Swap<16, big_endian>::writeval(wv + 1, lower_insn);
- gold_assert(!utils::has_overflow<25>(branch_offset));
+ gold_assert(!Bits<25>::has_overflow32(branch_offset));
return ((thumb2
- ? utils::has_overflow<25>(branch_offset)
- : utils::has_overflow<23>(branch_offset))
+ ? Bits<25>::has_overflow32(branch_offset)
+ : Bits<23>::has_overflow32(branch_offset))
? This::STATUS_OVERFLOW
: This::STATUS_OKAY);
}
@@ -4224,7 +4178,7 @@ Arm_relocate_functions<big_endian>::thm_jump19(
elfcpp::Swap<16, big_endian>::writeval(wv, upper_insn);
elfcpp::Swap<16, big_endian>::writeval(wv + 1, lower_insn);
- return (utils::has_overflow<21>(branch_offset)
+ return (Bits<21>::has_overflow32(branch_offset)
? This::STATUS_OVERFLOW
: This::STATUS_OKAY);
}
@@ -4239,11 +4193,22 @@ Target_arm<big_endian>::got_section(Symbol_table* symtab, Layout* layout)
{
gold_assert(symtab != NULL && layout != NULL);
+ // When using -z now, we can treat .got as a relro section.
+ // Without -z now, it is modified after program startup by lazy
+ // PLT relocations.
+ bool is_got_relro = parameters->options().now();
+ Output_section_order got_order = (is_got_relro
+ ? ORDER_RELRO_LAST
+ : ORDER_DATA);
+
+ // Unlike some targets (.e.g x86), ARM does not use separate .got and
+ // .got.plt sections in output. The output .got section contains both
+ // PLT and non-PLT GOT entries.
this->got_ = new Arm_output_data_got<big_endian>(symtab, layout);
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE),
- this->got_, ORDER_DATA, false);
+ this->got_, got_order, is_got_relro);
// The old GNU linker creates a .got.plt section. We just
// create another set of data in the .got section. Note that we
@@ -4252,7 +4217,7 @@ Target_arm<big_endian>::got_section(Symbol_table* symtab, Layout* layout)
this->got_plt_ = new Output_data_space(4, "** GOT PLT");
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE),
- this->got_plt_, ORDER_DATA, false);
+ this->got_plt_, got_order, is_got_relro);
// The first three entries are reserved.
this->got_plt_->set_current_data_size(3 * 4);
@@ -4352,11 +4317,11 @@ Stub_template::Stub_template(
break;
case Insn_template::THUMB32_TYPE:
- if (insns[i].r_type() != elfcpp::R_ARM_NONE)
+ if (insns[i].r_type() != elfcpp::R_ARM_NONE)
this->relocs_.push_back(Reloc(i, offset));
if (i == 0)
this->entry_in_thumb_mode_ = true;
- break;
+ break;
case Insn_template::ARM_TYPE:
// Handle cases where the target is encoded within the
@@ -4374,7 +4339,7 @@ Stub_template::Stub_template(
default:
gold_unreachable();
}
- offset += insn_size;
+ offset += insn_size;
}
this->size_ = offset;
}
@@ -4411,7 +4376,7 @@ Stub::do_fixed_endian_write(unsigned char* view, section_size_type view_size)
elfcpp::Swap<16, big_endian>::writeval(pov, hi);
elfcpp::Swap<16, big_endian>::writeval(pov + 2, lo);
}
- break;
+ break;
case Insn_template::ARM_TYPE:
case Insn_template::DATA_TYPE:
elfcpp::Swap<32, big_endian>::writeval(pov, insns[i].data());
@@ -4422,7 +4387,7 @@ Stub::do_fixed_endian_write(unsigned char* view, section_size_type view_size)
pov += insns[i].size();
}
gold_assert(static_cast<section_size_type>(pov - view) == view_size);
-}
+}
// Reloc_stub::Key methods.
@@ -4502,14 +4467,16 @@ Reloc_stub::stub_type_for_reloc(
}
int64_t branch_offset;
+ bool output_is_position_independent =
+ parameters->options().output_is_position_independent();
if (r_type == elfcpp::R_ARM_THM_CALL || r_type == elfcpp::R_ARM_THM_JUMP24)
{
// For THUMB BLX instruction, bit 1 of target comes from bit 1 of the
// base address (instruction address + 4).
if ((r_type == elfcpp::R_ARM_THM_CALL) && may_use_blx && !target_is_thumb)
- destination = utils::bit_select(destination, location, 0x2);
+ destination = Bits<32>::bit_select32(destination, location, 0x2);
branch_offset = static_cast<int64_t>(destination) - location;
-
+
// Handle cases where:
// - this call goes too far (different Thumb/Thumb2 max
// distance)
@@ -4530,7 +4497,7 @@ Reloc_stub::stub_type_for_reloc(
// Thumb to thumb.
if (!thumb_only)
{
- stub_type = (parameters->options().shared()
+ stub_type = (output_is_position_independent
|| should_force_pic_veneer)
// PIC stubs.
? ((may_use_blx
@@ -4551,7 +4518,7 @@ Reloc_stub::stub_type_for_reloc(
}
else
{
- stub_type = (parameters->options().shared()
+ stub_type = (output_is_position_independent
|| should_force_pic_veneer)
? arm_stub_long_branch_thumb_only_pic // PIC stub.
: arm_stub_long_branch_thumb_only; // non-PIC stub.
@@ -4560,11 +4527,11 @@ Reloc_stub::stub_type_for_reloc(
else
{
// Thumb to arm.
-
+
// FIXME: We should check that the input section is from an
// object that has interwork enabled.
- stub_type = (parameters->options().shared()
+ stub_type = (output_is_position_independent
|| should_force_pic_veneer)
// PIC stubs.
? ((may_use_blx
@@ -4606,7 +4573,7 @@ Reloc_stub::stub_type_for_reloc(
|| (r_type == elfcpp::R_ARM_JUMP24)
|| (r_type == elfcpp::R_ARM_PLT32))
{
- stub_type = (parameters->options().shared()
+ stub_type = (output_is_position_independent
|| should_force_pic_veneer)
// PIC stubs.
? (may_use_blx
@@ -4625,7 +4592,7 @@ Reloc_stub::stub_type_for_reloc(
if (branch_offset > ARM_MAX_FWD_BRANCH_OFFSET
|| (branch_offset < ARM_MAX_BWD_BRANCH_OFFSET))
{
- stub_type = (parameters->options().shared()
+ stub_type = (output_is_position_independent
|| should_force_pic_veneer)
? arm_stub_long_branch_any_arm_pic // PIC stubs.
: arm_stub_long_branch_any_any; /// non-PIC.
@@ -4661,16 +4628,16 @@ Stub_factory::Stub_factory()
{
// The instruction template sequences are declared as static
// objects and initialized first time the constructor runs.
-
+
// Arm/Thumb -> Arm/Thumb long branch stub. On V5T and above, use blx
// to reach the stub if necessary.
static const Insn_template elf32_arm_stub_long_branch_any_any[] =
{
Insn_template::arm_insn(0xe51ff004), // ldr pc, [pc, #-4]
Insn_template::data_word(0, elfcpp::R_ARM_ABS32, 0),
- // dcd R_ARM_ABS32(X)
+ // dcd R_ARM_ABS32(X)
};
-
+
// V4T Arm -> Thumb long branch stub. Used on V4T where blx is not
// available.
static const Insn_template elf32_arm_stub_long_branch_v4t_arm_thumb[] =
@@ -4678,9 +4645,9 @@ Stub_factory::Stub_factory()
Insn_template::arm_insn(0xe59fc000), // ldr ip, [pc, #0]
Insn_template::arm_insn(0xe12fff1c), // bx ip
Insn_template::data_word(0, elfcpp::R_ARM_ABS32, 0),
- // dcd R_ARM_ABS32(X)
+ // dcd R_ARM_ABS32(X)
};
-
+
// Thumb -> Thumb long branch stub. Used on M-profile architectures.
static const Insn_template elf32_arm_stub_long_branch_thumb_only[] =
{
@@ -4691,9 +4658,9 @@ Stub_factory::Stub_factory()
Insn_template::thumb16_insn(0x4760), // bx ip
Insn_template::thumb16_insn(0xbf00), // nop
Insn_template::data_word(0, elfcpp::R_ARM_ABS32, 0),
- // dcd R_ARM_ABS32(X)
+ // dcd R_ARM_ABS32(X)
};
-
+
// V4T Thumb -> Thumb long branch stub. Using the stack is not
// allowed.
static const Insn_template elf32_arm_stub_long_branch_v4t_thumb_thumb[] =
@@ -4703,9 +4670,9 @@ Stub_factory::Stub_factory()
Insn_template::arm_insn(0xe59fc000), // ldr ip, [pc, #0]
Insn_template::arm_insn(0xe12fff1c), // bx ip
Insn_template::data_word(0, elfcpp::R_ARM_ABS32, 0),
- // dcd R_ARM_ABS32(X)
+ // dcd R_ARM_ABS32(X)
};
-
+
// V4T Thumb -> ARM long branch stub. Used on V4T where blx is not
// available.
static const Insn_template elf32_arm_stub_long_branch_v4t_thumb_arm[] =
@@ -4714,9 +4681,9 @@ Stub_factory::Stub_factory()
Insn_template::thumb16_insn(0x46c0), // nop
Insn_template::arm_insn(0xe51ff004), // ldr pc, [pc, #-4]
Insn_template::data_word(0, elfcpp::R_ARM_ABS32, 0),
- // dcd R_ARM_ABS32(X)
+ // dcd R_ARM_ABS32(X)
};
-
+
// V4T Thumb -> ARM short branch stub. Shorter variant of the above
// one, when the destination is close enough.
static const Insn_template elf32_arm_stub_short_branch_v4t_thumb_arm[] =
@@ -4725,7 +4692,7 @@ Stub_factory::Stub_factory()
Insn_template::thumb16_insn(0x46c0), // nop
Insn_template::arm_rel_insn(0xea000000, -8), // b (X-8)
};
-
+
// ARM/Thumb -> ARM long branch stub, PIC. On V5T and above, use
// blx to reach the stub if necessary.
static const Insn_template elf32_arm_stub_long_branch_any_arm_pic[] =
@@ -4733,9 +4700,9 @@ Stub_factory::Stub_factory()
Insn_template::arm_insn(0xe59fc000), // ldr r12, [pc]
Insn_template::arm_insn(0xe08ff00c), // add pc, pc, ip
Insn_template::data_word(0, elfcpp::R_ARM_REL32, -4),
- // dcd R_ARM_REL32(X-4)
+ // dcd R_ARM_REL32(X-4)
};
-
+
// ARM/Thumb -> Thumb long branch stub, PIC. On V5T and above, use
// blx to reach the stub if necessary. We can not add into pc;
// it is not guaranteed to mode switch (different in ARMv6 and
@@ -4746,9 +4713,9 @@ Stub_factory::Stub_factory()
Insn_template::arm_insn(0xe08fc00c), // add ip, pc, ip
Insn_template::arm_insn(0xe12fff1c), // bx ip
Insn_template::data_word(0, elfcpp::R_ARM_REL32, 0),
- // dcd R_ARM_REL32(X)
+ // dcd R_ARM_REL32(X)
};
-
+
// V4T ARM -> ARM long branch stub, PIC.
static const Insn_template elf32_arm_stub_long_branch_v4t_arm_thumb_pic[] =
{
@@ -4756,9 +4723,9 @@ Stub_factory::Stub_factory()
Insn_template::arm_insn(0xe08fc00c), // add ip, pc, ip
Insn_template::arm_insn(0xe12fff1c), // bx ip
Insn_template::data_word(0, elfcpp::R_ARM_REL32, 0),
- // dcd R_ARM_REL32(X)
+ // dcd R_ARM_REL32(X)
};
-
+
// V4T Thumb -> ARM long branch stub, PIC.
static const Insn_template elf32_arm_stub_long_branch_v4t_thumb_arm_pic[] =
{
@@ -4767,9 +4734,9 @@ Stub_factory::Stub_factory()
Insn_template::arm_insn(0xe59fc000), // ldr ip, [pc, #0]
Insn_template::arm_insn(0xe08cf00f), // add pc, ip, pc
Insn_template::data_word(0, elfcpp::R_ARM_REL32, -4),
- // dcd R_ARM_REL32(X)
+ // dcd R_ARM_REL32(X)
};
-
+
// Thumb -> Thumb long branch stub, PIC. Used on M-profile
// architectures.
static const Insn_template elf32_arm_stub_long_branch_thumb_only_pic[] =
@@ -4781,9 +4748,9 @@ Stub_factory::Stub_factory()
Insn_template::thumb16_insn(0xbc01), // pop {r0}
Insn_template::thumb16_insn(0x4760), // bx ip
Insn_template::data_word(0, elfcpp::R_ARM_REL32, 4),
- // dcd R_ARM_REL32(X)
+ // dcd R_ARM_REL32(X)
};
-
+
// V4T Thumb -> Thumb long branch stub, PIC. Using the stack is not
// allowed.
static const Insn_template elf32_arm_stub_long_branch_v4t_thumb_thumb_pic[] =
@@ -4794,14 +4761,14 @@ Stub_factory::Stub_factory()
Insn_template::arm_insn(0xe08fc00c), // add ip, pc, ip
Insn_template::arm_insn(0xe12fff1c), // bx ip
Insn_template::data_word(0, elfcpp::R_ARM_REL32, 0),
- // dcd R_ARM_REL32(X)
+ // dcd R_ARM_REL32(X)
};
-
+
// Cortex-A8 erratum-workaround stubs.
-
+
// Stub used for conditional branches (which may be beyond +/-1MB away,
// so we can't use a conditional branch to reach this stub).
-
+
// original code:
//
// b<cond> X
@@ -4812,21 +4779,21 @@ Stub_factory::Stub_factory()
Insn_template::thumb16_bcond_insn(0xd001), // b<cond>.n true
Insn_template::thumb32_b_insn(0xf000b800, -4), // b.w after
Insn_template::thumb32_b_insn(0xf000b800, -4) // true:
- // b.w X
+ // b.w X
};
-
+
// Stub used for b.w and bl.w instructions.
-
+
static const Insn_template elf32_arm_stub_a8_veneer_b[] =
{
Insn_template::thumb32_b_insn(0xf000b800, -4) // b.w dest
};
-
+
static const Insn_template elf32_arm_stub_a8_veneer_bl[] =
{
Insn_template::thumb32_b_insn(0xf000b800, -4) // b.w dest
};
-
+
// Stub used for Thumb-2 blx.w instructions. We modified the original blx.w
// instruction (which switches to ARM mode) to point to this stub. Jump to
// the real destination using an ARM-mode branch.
@@ -5047,7 +5014,7 @@ Stub_table<big_endian>::update_data_size_and_addralign()
// Update prev_data_size_ and prev_addralign_. These will be used
// as the current data size and address alignment for the next pass.
bool changed = size != this->prev_data_size_;
- this->prev_data_size_ = size;
+ this->prev_data_size_ = size;
if (addralign != this->prev_addralign_)
changed = true;
@@ -5181,7 +5148,7 @@ Arm_input_section<big_endian>::do_write(Output_file* of)
// We have to write out the original section content.
gold_assert(this->original_contents_ != NULL);
of->write(this->offset(), this->original_contents_,
- this->original_size_);
+ this->original_size_);
// If this owns a stub table and it is not empty, write it.
if (this->is_stub_table_owner() && !this->stub_table_->empty())
@@ -5240,8 +5207,6 @@ Arm_exidx_cantunwind::do_fixed_endian_write(Output_file* of)
off_t offset = this->offset();
const section_size_type oview_size = 8;
unsigned char* const oview = of->get_output_view(offset, oview_size);
-
- typedef typename elfcpp::Swap_unaligned<32, big_endian>::Valtype Valtype;
Output_section* os = this->relobj_->output_section(this->shndx_);
gold_assert(os != NULL);
@@ -5258,7 +5223,7 @@ Arm_exidx_cantunwind::do_fixed_endian_write(Output_file* of)
{
section_start = os->address() + output_offset;
const Arm_exidx_input_section* exidx_input_section =
- arm_relobj->exidx_input_section_by_link(this->shndx_);
+ arm_relobj->exidx_input_section_by_link(this->shndx_);
gold_assert(exidx_input_section != NULL);
section_size =
convert_to_section_size_type(exidx_input_section->text_size());
@@ -5280,7 +5245,7 @@ Arm_exidx_cantunwind::do_fixed_endian_write(Output_file* of)
// or after the end of a text section. The second word is the special
// EXIDX_CANTUNWIND value.
uint32_t prel31_offset = output_address - this->address();
- if (utils::has_overflow<31>(offset))
+ if (Bits<31>::has_overflow32(offset))
gold_error(_("PREL31 overflow in EXIDX_CANTUNWIND entry"));
elfcpp::Swap_unaligned<32, big_endian>::writeval(oview,
prel31_offset & 0x7fffffffU);
@@ -5338,7 +5303,7 @@ Arm_exidx_merged_section::build_contents(
section_offset_type out_max =
convert_types<section_offset_type>(this->data_size());
for (Arm_exidx_section_offset_map::const_iterator p =
- this->section_offset_map_.begin();
+ this->section_offset_map_.begin();
p != this->section_offset_map_.end();
++p)
{
@@ -5410,7 +5375,7 @@ Arm_exidx_merged_section::do_output_offset(
// Offset is discarded owing to EXIDX entry merging.
*poutput = -1;
}
-
+
return true;
}
@@ -5422,7 +5387,7 @@ Arm_exidx_merged_section::do_write(Output_file* of)
off_t offset = this->offset();
const section_size_type oview_size = this->data_size();
unsigned char* const oview = of->get_output_view(offset, oview_size);
-
+
Output_section* os = this->relobj()->output_section(this->shndx());
gold_assert(os != NULL);
@@ -5533,7 +5498,7 @@ Arm_exidx_fixup::process_exidx_section(
this->last_unwind_type_ = UT_NONE;
return 0;
}
-
+
uint32_t deleted_bytes = 0;
bool prev_delete_entry = false;
gold_assert(this->section_offset_map_ == NULL);
@@ -5566,7 +5531,7 @@ Arm_exidx_fixup::process_exidx_section(
prev_delete_entry = delete_entry;
}
-
+
// If section offset map is not NULL, make an entry for the end of
// section.
if (this->section_offset_map_ != NULL)
@@ -5575,7 +5540,7 @@ Arm_exidx_fixup::process_exidx_section(
*psection_offset_map = this->section_offset_map_;
this->section_offset_map_ = NULL;
this->last_input_section_ = exidx_input_section;
-
+
// Set the first output text section so that we can link the EXIDX output
// section to it. Ignore any EXIDX input section that is completely merged.
if (this->first_output_text_section_ == NULL
@@ -5608,14 +5573,14 @@ Arm_output_section<big_endian>::create_stub_group(
// We use a different kind of relaxed section in an EXIDX section.
// The static casting from Output_relaxed_input_section to
// Arm_input_section is invalid in an EXIDX section. We are okay
- // because we should not be calling this for an EXIDX section.
+ // because we should not be calling this for an EXIDX section.
gold_assert(this->type() != elfcpp::SHT_ARM_EXIDX);
// Currently we convert ordinary input sections into relaxed sections only
// at this point but we may want to support creating relaxed input section
// very early. So we check here to see if owner is already a relaxed
// section.
-
+
Arm_input_section<big_endian>* arm_input_section;
if (owner->is_relaxed_input_section())
{
@@ -5639,7 +5604,7 @@ Arm_output_section<big_endian>::create_stub_group(
target->new_stub_table(arm_input_section);
arm_input_section->set_stub_table(stub_table);
-
+
Input_section_list::const_iterator p = begin;
Input_section_list::const_iterator prev_p;
@@ -5664,7 +5629,7 @@ Arm_output_section<big_endian>::create_stub_group(
// size is just below GROUP_SIZE. The last input section will be converted
// into a stub table. If STUB_ALWAYS_AFTER_BRANCH is false, we also add
// input section after the stub table, effectively double the group size.
-//
+//
// This is similar to the group_sections() function in elf32-arm.c but is
// implemented differently.
@@ -5715,8 +5680,8 @@ Arm_output_section<big_endian>::group_sections(
section_size_type section_begin_offset =
align_address(off, p->addralign());
section_size_type section_end_offset =
- section_begin_offset + p->data_size();
-
+ section_begin_offset + p->data_size();
+
// Check to see if we should group the previously seen sections.
switch (state)
{
@@ -5728,7 +5693,7 @@ Arm_output_section<big_endian>::group_sections(
if (section_end_offset - group_begin_offset >= group_size)
{
if (stubs_always_after_branch)
- {
+ {
gold_assert(group_end != this->input_sections().end());
this->create_stub_group(group_begin, group_end, group_end,
target, &new_relaxed_sections,
@@ -5761,7 +5726,7 @@ Arm_output_section<big_endian>::group_sections(
default:
gold_unreachable();
- }
+ }
// If we see an input section and currently there is no group, start
// a new one. Skip any empty sections. We look at the data size
@@ -5858,7 +5823,7 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
if (!this->input_sections().empty())
gold_error(_("Found non-EXIDX input sections in EXIDX output section"));
-
+
// Go through all the known input sections and record them.
typedef Unordered_set<Section_id, Section_id_hash> Section_id_set;
typedef Unordered_map<Section_id, const Output_section::Input_section*,
@@ -5928,12 +5893,12 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
Task_lock_obj<Object> tl(task, exidx_relobj);
section_size_type exidx_size;
const unsigned char* exidx_contents =
- exidx_relobj->section_contents(exidx_shndx, &exidx_size, false);
+ exidx_relobj->section_contents(exidx_shndx, &exidx_size, false);
// Fix up coverage and append input section to output data list.
Arm_exidx_section_offset_map* section_offset_map = NULL;
uint32_t deleted_bytes =
- exidx_fixup.process_exidx_section<big_endian>(exidx_input_section,
+ exidx_fixup.process_exidx_section<big_endian>(exidx_input_section,
exidx_contents,
exidx_size,
&section_offset_map);
@@ -5977,7 +5942,7 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
this->add_script_input_section(*pis);
}
- processed_input_sections.insert(Section_id(exidx_relobj, exidx_shndx));
+ processed_input_sections.insert(Section_id(exidx_relobj, exidx_shndx));
}
// Insert an EXIDX_CANTUNWIND entry at the end of output if necessary.
@@ -6012,7 +5977,7 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
arm_relobj->set_output_local_symbol_count_needs_update();
}
}
-
+
// Link exidx output section to the first seen output section and
// set correct entry size.
this->set_link_section(exidx_fixup.first_output_text_section());
@@ -6219,7 +6184,7 @@ Arm_relobj<big_endian>::scan_section_for_cortex_a8_erratum(
// scan. There are two reasons. First, we should look at THUMB code and
// THUMB code only. Second, we only want to look at the 4K-page boundary
// to speed up the scanning.
-
+
while (p != this->mapping_symbols_info_.end()
&& p->first.first == shndx)
{
@@ -6238,7 +6203,7 @@ Arm_relobj<big_endian>::scan_section_for_cortex_a8_erratum(
span_end = convert_to_section_size_type(next->first.second);
else
span_end = convert_to_section_size_type(shdr.get_sh_size());
-
+
if (((span_start + output_address) & ~0xfffUL)
!= ((span_end + output_address - 1) & ~0xfffUL))
{
@@ -6249,7 +6214,7 @@ Arm_relobj<big_endian>::scan_section_for_cortex_a8_erratum(
}
}
- p = next;
+ p = next;
}
}
@@ -6365,7 +6330,7 @@ Arm_relobj<big_endian>::scan_sections_for_stubs(
// do_count_local_symbol in parent and scan local symbols to mark
// THUMB functions. This is not the most efficient way but I do not want to
// slow down other ports by calling a per symbol target hook inside
-// Sized_relobj_file<size, big_endian>::do_count_local_symbols.
+// Sized_relobj_file<size, big_endian>::do_count_local_symbols.
template<bool big_endian>
void
@@ -6375,7 +6340,7 @@ Arm_relobj<big_endian>::do_count_local_symbols(
{
// We need to fix-up the values of any local symbols whose type are
// STT_ARM_TFUNC.
-
+
// Ask parent to count the local symbols.
Sized_relobj_file<32, big_endian>::do_count_local_symbols(pool, dynpool);
const unsigned int loccount = this->local_symbol_count();
@@ -6412,7 +6377,7 @@ Arm_relobj<big_endian>::do_count_local_symbols(
if (strtabshdr.get_sh_type() != elfcpp::SHT_STRTAB)
{
this->error(_("symbol table name section has wrong type: %u"),
- static_cast<unsigned int>(strtabshdr.get_sh_type()));
+ static_cast<unsigned int>(strtabshdr.get_sh_type()));
return;
}
const char* pnames =
@@ -6472,7 +6437,7 @@ Arm_relobj<big_endian>::do_relocate_sections(
{
// Call parent to relocate sections.
Sized_relobj_file<32, big_endian>::do_relocate_sections(symtab, layout,
- pshdrs, of, pviews);
+ pshdrs, of, pviews);
// We do not generate stubs if doing a relocatable link.
if (parameters->options().relocatable())
@@ -6520,7 +6485,7 @@ Arm_relobj<big_endian>::do_relocate_sections(
unsigned char* view = (*pviews)[i].view + offset;
Arm_address address = stub_table->address();
section_size_type view_size = stub_table->data_size();
-
+
stub_table->relocate_stubs(&relinfo, arm_target, os, view, address,
view_size);
}
@@ -6578,7 +6543,7 @@ Arm_relobj<big_endian>::find_linked_text_section(
unsigned int* pshndx)
{
elfcpp::Shdr<32, big_endian> shdr(pshdr);
-
+
// If there is no relocation, we cannot find the linked text section.
size_t reloc_size;
if (shdr.get_sh_type() == elfcpp::SHT_REL)
@@ -6586,10 +6551,10 @@ Arm_relobj<big_endian>::find_linked_text_section(
else
reloc_size = elfcpp::Elf_sizes<32>::rela_size;
size_t reloc_count = shdr.get_sh_size() / reloc_size;
-
+
// Get the relocations.
const unsigned char* prelocs =
- this->get_view(shdr.get_sh_offset(), shdr.get_sh_size(), true, false);
+ this->get_view(shdr.get_sh_offset(), shdr.get_sh_size(), true, false);
// Find the REL31 relocation for the first word of the first EXIDX entry.
for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
@@ -6665,7 +6630,7 @@ Arm_relobj<big_endian>::make_exidx_input_section(
this->section_name(shndx).c_str(), shndx, text_shndx,
this->name().c_str());
exidx_input_section->set_has_errors();
- }
+ }
else if (this->exidx_section_map_[text_shndx] != NULL)
{
unsigned other_exidx_shndx =
@@ -6756,7 +6721,7 @@ Arm_relobj<big_endian>::do_read_symbols(Read_symbols_data* sd)
if (shdr.get_sh_type() == elfcpp::SHT_ARM_ATTRIBUTES)
{
- gold_assert(this->attributes_section_data_ == NULL);
+ gold_assert(this->attributes_section_data_ == NULL);
section_offset_type section_offset = shdr.get_sh_offset();
section_size_type section_size =
convert_to_section_size_type(shdr.get_sh_size());
@@ -6791,7 +6756,7 @@ Arm_relobj<big_endian>::do_read_symbols(Read_symbols_data* sd)
return;
}
- // Some tools are broken and they do not set the link of EXIDX sections.
+ // Some tools are broken and they do not set the link of EXIDX sections.
// We look at the first relocation to figure out the linked sections.
if (!deferred_exidx_sections.empty())
{
@@ -6837,7 +6802,7 @@ Arm_relobj<big_endian>::do_read_symbols(Read_symbols_data* sd)
const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
locsize, true, true);
- // Process the deferred EXIDX sections.
+ // Process the deferred EXIDX sections.
for (unsigned int i = 0; i < deferred_exidx_sections.size(); ++i)
{
unsigned int shndx = deferred_exidx_sections[i];
@@ -6855,7 +6820,7 @@ Arm_relobj<big_endian>::do_read_symbols(Read_symbols_data* sd)
}
// Process relocations for garbage collection. The ARM target uses .ARM.exidx
-// sections for unwinding. These sections are referenced implicitly by
+// sections for unwinding. These sections are referenced implicitly by
// text sections linked in the section headers. If we ignore these implicit
// references, the .ARM.exidx sections and any .ARM.extab sections they use
// will be garbage-collected incorrectly. Hence we override the same function
@@ -6874,7 +6839,7 @@ Arm_relobj<big_endian>::do_gc_process_relocs(Symbol_table* symtab,
// This happens when --icf is used but --gc-sections is not.
if (!parameters->options().gc_sections())
return;
-
+
unsigned int shnum = this->shnum();
const unsigned int shdr_size = elfcpp::Elf_sizes<32>::shdr_size;
const unsigned char* pshdrs = this->get_view(this->elf_file()->shoff(),
@@ -6979,7 +6944,7 @@ Arm_relobj<big_endian>::update_output_local_symbol_count()
// that is discarded due to entry merging.
lv.set_no_output_symtab_entry();
continue;
- }
+ }
}
}
@@ -7042,8 +7007,8 @@ Stub_addend_reader<elfcpp::SHT_REL, big_endian>::operator()(
const unsigned char* view,
const typename Reloc_types<elfcpp::SHT_REL, 32, big_endian>::Reloc&) const
{
- typedef struct Arm_relocate_functions<big_endian> RelocFuncs;
-
+ typedef class Arm_relocate_functions<big_endian> RelocFuncs;
+
switch (r_type)
{
case elfcpp::R_ARM_CALL:
@@ -7053,7 +7018,7 @@ Stub_addend_reader<elfcpp::SHT_REL, big_endian>::operator()(
typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
const Valtype* wv = reinterpret_cast<const Valtype*>(view);
Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
- return utils::sign_extend<26>(val << 2);
+ return Bits<26>::sign_extend32(val << 2);
}
case elfcpp::R_ARM_THM_CALL:
@@ -7101,7 +7066,7 @@ Arm_output_data_got<big_endian>::add_tls_gd32_with_static_reloc(
// We are doing a static link. Just mark it as belong to module 1,
// the executable.
unsigned int got_offset = this->add_constant(1);
- gsym->set_got_offset(got_type, got_offset);
+ gsym->set_got_offset(got_type, got_offset);
got_offset = this->add_constant(0);
this->static_relocs_.push_back(Static_reloc(got_offset,
elfcpp::R_ARM_TLS_DTPOFF32,
@@ -7125,8 +7090,8 @@ Arm_output_data_got<big_endian>::add_tls_gd32_with_static_reloc(
unsigned int got_offset = this->add_constant(1);
object->set_local_got_offset(index, got_type, got_offset);
got_offset = this->add_constant(0);
- this->static_relocs_.push_back(Static_reloc(got_offset,
- elfcpp::R_ARM_TLS_DTPOFF32,
+ this->static_relocs_.push_back(Static_reloc(got_offset,
+ elfcpp::R_ARM_TLS_DTPOFF32,
object, index));
}
@@ -7150,7 +7115,7 @@ Arm_output_data_got<big_endian>::do_write(Output_file* of)
Output_segment* tls_segment = this->layout_->tls_segment();
gold_assert(tls_segment != NULL);
-
+
// The thread pointer $tp points to the TCB, which is followed by the
// TLS. So we need to adjust $tp relative addressing by this amount.
Arm_address aligned_tcb_size =
@@ -7159,7 +7124,7 @@ Arm_output_data_got<big_endian>::do_write(Output_file* of)
for (size_t i = 0; i < this->static_relocs_.size(); ++i)
{
Static_reloc& reloc(this->static_relocs_[i]);
-
+
Arm_address value;
if (!reloc.symbol_is_global())
{
@@ -7182,7 +7147,7 @@ Arm_output_data_got<big_endian>::do_write(Output_file* of)
reloc.index(), reloc.relobj()->name().c_str());
continue;
}
-
+
value = psymval->value(object, 0);
}
else
@@ -7238,6 +7203,9 @@ Arm_output_data_got<big_endian>::do_write(Output_file* of)
}
// A class to handle the PLT data.
+// This is an abstract base class that handles most of the linker details
+// but does not know the actual contents of PLT entries. The derived
+// classes below fill in those details.
template<bool big_endian>
class Output_data_plt_arm : public Output_section_data
@@ -7246,7 +7214,7 @@ class Output_data_plt_arm : public Output_section_data
typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, big_endian>
Reloc_section;
- Output_data_plt_arm(Layout*, Output_data_space*);
+ Output_data_plt_arm(Layout*, uint64_t addralign, Output_data_space*);
// Add an entry to the PLT.
void
@@ -7263,16 +7231,49 @@ class Output_data_plt_arm : public Output_section_data
{ return this->count_; }
// Return the offset of the first non-reserved PLT entry.
- static unsigned int
- first_plt_entry_offset()
- { return sizeof(first_plt_entry); }
+ unsigned int
+ first_plt_entry_offset() const
+ { return this->do_first_plt_entry_offset(); }
// Return the size of a PLT entry.
- static unsigned int
- get_plt_entry_size()
- { return sizeof(plt_entry); }
+ unsigned int
+ get_plt_entry_size() const
+ { return this->do_get_plt_entry_size(); }
protected:
+ // Fill in the first PLT entry.
+ void
+ fill_first_plt_entry(unsigned char* pov,
+ Arm_address got_address,
+ Arm_address plt_address)
+ { this->do_fill_first_plt_entry(pov, got_address, plt_address); }
+
+ void
+ fill_plt_entry(unsigned char* pov,
+ Arm_address got_address,
+ Arm_address plt_address,
+ unsigned int got_offset,
+ unsigned int plt_offset)
+ { do_fill_plt_entry(pov, got_address, plt_address, got_offset, plt_offset); }
+
+ virtual unsigned int
+ do_first_plt_entry_offset() const = 0;
+
+ virtual unsigned int
+ do_get_plt_entry_size() const = 0;
+
+ virtual void
+ do_fill_first_plt_entry(unsigned char* pov,
+ Arm_address got_address,
+ Arm_address plt_address) = 0;
+
+ virtual void
+ do_fill_plt_entry(unsigned char* pov,
+ Arm_address got_address,
+ Arm_address plt_address,
+ unsigned int got_offset,
+ unsigned int plt_offset) = 0;
+
void
do_adjust_output_section(Output_section* os);
@@ -7282,18 +7283,12 @@ class Output_data_plt_arm : public Output_section_data
{ mapfile->print_output_data(this, _("** PLT")); }
private:
- // Template for the first PLT entry.
- static const uint32_t first_plt_entry[5];
-
- // Template for subsequent PLT entries.
- static const uint32_t plt_entry[3];
-
// Set the final size.
void
set_final_data_size()
{
- this->set_data_size(sizeof(first_plt_entry)
- + this->count_ * sizeof(plt_entry));
+ this->set_data_size(this->first_plt_entry_offset()
+ + this->count_ * this->get_plt_entry_size());
}
// Write out the PLT data.
@@ -7314,8 +7309,9 @@ class Output_data_plt_arm : public Output_section_data
template<bool big_endian>
Output_data_plt_arm<big_endian>::Output_data_plt_arm(Layout* layout,
+ uint64_t addralign,
Output_data_space* got_plt)
- : Output_section_data(4), got_plt_(got_plt), count_(0)
+ : Output_section_data(addralign), got_plt_(got_plt), count_(0)
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
@@ -7340,8 +7336,8 @@ Output_data_plt_arm<big_endian>::add_entry(Symbol* gsym)
// Note that when setting the PLT offset we skip the initial
// reserved PLT entry.
- gsym->set_plt_offset((this->count_) * sizeof(plt_entry)
- + sizeof(first_plt_entry));
+ gsym->set_plt_offset((this->count_) * this->get_plt_entry_size()
+ + this->first_plt_entry_offset());
++this->count_;
@@ -7362,6 +7358,45 @@ Output_data_plt_arm<big_endian>::add_entry(Symbol* gsym)
// appear in the relocations.
}
+template<bool big_endian>
+class Output_data_plt_arm_standard : public Output_data_plt_arm<big_endian>
+{
+ public:
+ Output_data_plt_arm_standard(Layout* layout, Output_data_space* got_plt)
+ : Output_data_plt_arm<big_endian>(layout, 4, got_plt)
+ { }
+
+ protected:
+ // Return the offset of the first non-reserved PLT entry.
+ virtual unsigned int
+ do_first_plt_entry_offset() const
+ { return sizeof(first_plt_entry); }
+
+ // Return the size of a PLT entry.
+ virtual unsigned int
+ do_get_plt_entry_size() const
+ { return sizeof(plt_entry); }
+
+ virtual void
+ do_fill_first_plt_entry(unsigned char* pov,
+ Arm_address got_address,
+ Arm_address plt_address);
+
+ virtual void
+ do_fill_plt_entry(unsigned char* pov,
+ Arm_address got_address,
+ Arm_address plt_address,
+ unsigned int got_offset,
+ unsigned int plt_offset);
+
+ private:
+ // Template for the first PLT entry.
+ static const uint32_t first_plt_entry[5];
+
+ // Template for subsequent PLT entries.
+ static const uint32_t plt_entry[3];
+};
+
// ARM PLTs.
// FIXME: This is not very flexible. Right now this has only been tested
// on armv5te. If we are to support additional architecture features like
@@ -7369,25 +7404,63 @@ Output_data_plt_arm<big_endian>::add_entry(Symbol* gsym)
// The first entry in the PLT.
template<bool big_endian>
-const uint32_t Output_data_plt_arm<big_endian>::first_plt_entry[5] =
+const uint32_t Output_data_plt_arm_standard<big_endian>::first_plt_entry[5] =
{
0xe52de004, // str lr, [sp, #-4]!
0xe59fe004, // ldr lr, [pc, #4]
- 0xe08fe00e, // add lr, pc, lr
+ 0xe08fe00e, // add lr, pc, lr
0xe5bef008, // ldr pc, [lr, #8]!
0x00000000, // &GOT[0] - .
};
+template<bool big_endian>
+void
+Output_data_plt_arm_standard<big_endian>::do_fill_first_plt_entry(
+ unsigned char* pov,
+ Arm_address got_address,
+ Arm_address plt_address)
+{
+ // Write first PLT entry. All but the last word are constants.
+ const size_t num_first_plt_words = (sizeof(first_plt_entry)
+ / sizeof(plt_entry[0]));
+ for (size_t i = 0; i < num_first_plt_words - 1; i++)
+ elfcpp::Swap<32, big_endian>::writeval(pov + i * 4, first_plt_entry[i]);
+ // Last word in first PLT entry is &GOT[0] - .
+ elfcpp::Swap<32, big_endian>::writeval(pov + 16,
+ got_address - (plt_address + 16));
+}
+
// Subsequent entries in the PLT.
template<bool big_endian>
-const uint32_t Output_data_plt_arm<big_endian>::plt_entry[3] =
+const uint32_t Output_data_plt_arm_standard<big_endian>::plt_entry[3] =
{
0xe28fc600, // add ip, pc, #0xNN00000
0xe28cca00, // add ip, ip, #0xNN000
0xe5bcf000, // ldr pc, [ip, #0xNNN]!
};
+template<bool big_endian>
+void
+Output_data_plt_arm_standard<big_endian>::do_fill_plt_entry(
+ unsigned char* pov,
+ Arm_address got_address,
+ Arm_address plt_address,
+ unsigned int got_offset,
+ unsigned int plt_offset)
+{
+ int32_t offset = ((got_address + got_offset)
+ - (plt_address + plt_offset + 8));
+
+ gold_assert(offset >= 0 && offset < 0x0fffffff);
+ uint32_t plt_insn0 = plt_entry[0] | ((offset >> 20) & 0xff);
+ elfcpp::Swap<32, big_endian>::writeval(pov, plt_insn0);
+ uint32_t plt_insn1 = plt_entry[1] | ((offset >> 12) & 0xff);
+ elfcpp::Swap<32, big_endian>::writeval(pov + 4, plt_insn1);
+ uint32_t plt_insn2 = plt_entry[2] | (offset & 0xfff);
+ elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2);
+}
+
// Write out the PLT. This uses the hand-coded instructions above,
// and adjusts them as needed. This is all specified by the arm ELF
// Processor Supplement.
@@ -7411,46 +7484,29 @@ Output_data_plt_arm<big_endian>::do_write(Output_file* of)
Arm_address plt_address = this->address();
Arm_address got_address = this->got_plt_->address();
- // Write first PLT entry. All but the last word are constants.
- const size_t num_first_plt_words = (sizeof(first_plt_entry)
- / sizeof(plt_entry[0]));
- for (size_t i = 0; i < num_first_plt_words - 1; i++)
- elfcpp::Swap<32, big_endian>::writeval(pov + i * 4, first_plt_entry[i]);
- // Last word in first PLT entry is &GOT[0] - .
- elfcpp::Swap<32, big_endian>::writeval(pov + 16,
- got_address - (plt_address + 16));
- pov += sizeof(first_plt_entry);
+ // Write first PLT entry.
+ this->fill_first_plt_entry(pov, got_address, plt_address);
+ pov += this->first_plt_entry_offset();
unsigned char* got_pov = got_view;
memset(got_pov, 0, 12);
got_pov += 12;
- const int rel_size = elfcpp::Elf_sizes<32>::rel_size;
- unsigned int plt_offset = sizeof(first_plt_entry);
- unsigned int plt_rel_offset = 0;
+ unsigned int plt_offset = this->first_plt_entry_offset();
unsigned int got_offset = 12;
const unsigned int count = this->count_;
for (unsigned int i = 0;
i < count;
++i,
- pov += sizeof(plt_entry),
+ pov += this->get_plt_entry_size(),
got_pov += 4,
- plt_offset += sizeof(plt_entry),
- plt_rel_offset += rel_size,
+ plt_offset += this->get_plt_entry_size(),
got_offset += 4)
{
// Set and adjust the PLT entry itself.
- int32_t offset = ((got_address + got_offset)
- - (plt_address + plt_offset + 8));
-
- gold_assert(offset >= 0 && offset < 0x0fffffff);
- uint32_t plt_insn0 = plt_entry[0] | ((offset >> 20) & 0xff);
- elfcpp::Swap<32, big_endian>::writeval(pov, plt_insn0);
- uint32_t plt_insn1 = plt_entry[1] | ((offset >> 12) & 0xff);
- elfcpp::Swap<32, big_endian>::writeval(pov + 4, plt_insn1);
- uint32_t plt_insn2 = plt_entry[2] | (offset & 0xfff);
- elfcpp::Swap<32, big_endian>::writeval(pov + 8, plt_insn2);
+ this->fill_plt_entry(pov, got_address, plt_address,
+ got_offset, plt_offset);
// Set the entry in the GOT.
elfcpp::Swap<32, big_endian>::writeval(got_pov, plt_address);
@@ -7478,7 +7534,8 @@ Target_arm<big_endian>::make_plt_entry(Symbol_table* symtab, Layout* layout,
// Create the GOT sections first.
this->got_section(symtab, layout);
- this->plt_ = new Output_data_plt_arm<big_endian>(layout, this->got_plt_);
+ this->plt_ = this->make_data_plt(layout, this->got_plt_);
+
layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR),
@@ -7504,7 +7561,7 @@ template<bool big_endian>
unsigned int
Target_arm<big_endian>::first_plt_entry_offset() const
{
- return Output_data_plt_arm<big_endian>::first_plt_entry_offset();
+ return this->plt_->first_plt_entry_offset();
}
// Return the size of each PLT entry.
@@ -7513,7 +7570,7 @@ template<bool big_endian>
unsigned int
Target_arm<big_endian>::plt_entry_size() const
{
- return Output_data_plt_arm<big_endian>::get_plt_entry_size();
+ return this->plt_->get_plt_entry_size();
}
// Get the section to use for TLS_DESC relocations.
@@ -7823,8 +7880,8 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
{
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
- // If we are to add more other reloc types than R_ARM_ABS32,
- // we need to add check_non_pic(object, r_type) here.
+ // If we are to add more other reloc types than R_ARM_ABS32,
+ // we need to add check_non_pic(object, r_type) here.
rel_dyn->add_local_relative(object, r_sym, elfcpp::R_ARM_RELATIVE,
output_section, data_shndx,
reloc.get_r_offset());
@@ -7846,16 +7903,16 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
// data section, we need to be careful not to apply this
// relocation statically.
if (parameters->options().output_is_position_independent())
- {
+ {
check_non_pic(object, r_type);
- Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+ Reloc_section* rel_dyn = target->rel_dyn_section(layout);
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
- if (lsym.get_st_type() != elfcpp::STT_SECTION)
+ if (lsym.get_st_type() != elfcpp::STT_SECTION)
rel_dyn->add_local(object, r_sym, r_type, output_section,
data_shndx, reloc.get_r_offset());
- else
- {
- gold_assert(lsym.get_st_value() == 0);
+ else
+ {
+ gold_assert(lsym.get_st_value() == 0);
unsigned int shndx = lsym.get_st_shndx();
bool is_ordinary;
shndx = object->adjust_sym_shndx(r_sym, shndx,
@@ -7867,8 +7924,8 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
rel_dyn->add_local_section(object, shndx,
r_type, output_section,
data_shndx, reloc.get_r_offset());
- }
- }
+ }
+ }
break;
case elfcpp::R_ARM_REL32:
@@ -7985,18 +8042,18 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
{
bool output_is_shared = parameters->options().shared();
const tls::Tls_optimization optimized_type
- = Target_arm<big_endian>::optimize_tls_reloc(!output_is_shared,
+ = Target_arm<big_endian>::optimize_tls_reloc(!output_is_shared,
r_type);
switch (r_type)
{
case elfcpp::R_ARM_TLS_GD32: // Global-dynamic
if (optimized_type == tls::TLSOPT_NONE)
{
- // Create a pair of GOT entries for the module index and
- // dtv-relative offset.
- Arm_output_data_got<big_endian>* got
- = target->got_section(symtab, layout);
- unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+ // Create a pair of GOT entries for the module index and
+ // dtv-relative offset.
+ Arm_output_data_got<big_endian>* got
+ = target->got_section(symtab, layout);
+ unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
unsigned int shndx = lsym.get_st_shndx();
bool is_ordinary;
shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
@@ -8024,8 +8081,8 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
case elfcpp::R_ARM_TLS_LDM32: // Local-dynamic
if (optimized_type == tls::TLSOPT_NONE)
{
- // Create a GOT entry for the module index.
- target->got_mod_index_entry(symtab, layout, object);
+ // Create a GOT entry for the module index.
+ target->got_mod_index_entry(symtab, layout, object);
}
else
// FIXME: TLS optimization not supported yet.
@@ -8068,9 +8125,9 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
layout->set_has_static_tls();
if (output_is_shared)
{
- // We need to create a dynamic relocation.
- gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
- unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+ // We need to create a dynamic relocation.
+ gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
+ unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
rel_dyn->add_local(object, r_sym, elfcpp::R_ARM_TLS_TPOFF32,
output_section, data_shndx,
@@ -8216,42 +8273,42 @@ Target_arm<big_endian>::Scan::global(Symbol_table* symtab,
case elfcpp::R_ARM_ABS32_NOI:
// Absolute addressing relocations.
{
- // Make a PLT entry if necessary.
- if (this->symbol_needs_plt_entry(gsym))
- {
- target->make_plt_entry(symtab, layout, gsym);
- // Since this is not a PC-relative relocation, we may be
- // taking the address of a function. In that case we need to
- // set the entry in the dynamic symbol table to the address of
- // the PLT entry.
- if (gsym->is_from_dynobj() && !parameters->options().shared())
- gsym->set_needs_dynsym_value();
- }
- // Make a dynamic relocation if necessary.
- if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
- {
- if (gsym->may_need_copy_reloc())
- {
- target->copy_reloc(symtab, layout, object,
- data_shndx, output_section, gsym, reloc);
- }
- else if ((r_type == elfcpp::R_ARM_ABS32
+ // Make a PLT entry if necessary.
+ if (this->symbol_needs_plt_entry(gsym))
+ {
+ target->make_plt_entry(symtab, layout, gsym);
+ // Since this is not a PC-relative relocation, we may be
+ // taking the address of a function. In that case we need to
+ // set the entry in the dynamic symbol table to the address of
+ // the PLT entry.
+ if (gsym->is_from_dynobj() && !parameters->options().shared())
+ gsym->set_needs_dynsym_value();
+ }
+ // Make a dynamic relocation if necessary.
+ if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
+ {
+ if (gsym->may_need_copy_reloc())
+ {
+ target->copy_reloc(symtab, layout, object,
+ data_shndx, output_section, gsym, reloc);
+ }
+ else if ((r_type == elfcpp::R_ARM_ABS32
|| r_type == elfcpp::R_ARM_ABS32_NOI)
- && gsym->can_use_relative_reloc(false))
- {
- Reloc_section* rel_dyn = target->rel_dyn_section(layout);
- rel_dyn->add_global_relative(gsym, elfcpp::R_ARM_RELATIVE,
- output_section, object,
- data_shndx, reloc.get_r_offset());
- }
- else
- {
+ && gsym->can_use_relative_reloc(false))
+ {
+ Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+ rel_dyn->add_global_relative(gsym, elfcpp::R_ARM_RELATIVE,
+ output_section, object,
+ data_shndx, reloc.get_r_offset());
+ }
+ else
+ {
check_non_pic(object, r_type);
- Reloc_section* rel_dyn = target->rel_dyn_section(layout);
- rel_dyn->add_global(gsym, r_type, output_section, object,
- data_shndx, reloc.get_r_offset());
- }
- }
+ Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+ rel_dyn->add_global(gsym, r_type, output_section, object,
+ data_shndx, reloc.get_r_offset());
+ }
+ }
}
break;
@@ -8260,7 +8317,7 @@ Target_arm<big_endian>::Scan::global(Symbol_table* symtab,
// We need a GOT section.
target->got_section(symtab, layout);
break;
-
+
case elfcpp::R_ARM_REL32:
case elfcpp::R_ARM_LDR_PC_G0:
case elfcpp::R_ARM_SBREL32:
@@ -8377,7 +8434,9 @@ Target_arm<big_endian>::Scan::global(Symbol_table* symtab,
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
if (gsym->is_from_dynobj()
|| gsym->is_undefined()
- || gsym->is_preemptible())
+ || gsym->is_preemptible()
+ || (gsym->visibility() == elfcpp::STV_PROTECTED
+ && parameters->options().shared()))
got->add_global_with_rel(gsym, GOT_TYPE_STANDARD,
rel_dyn, elfcpp::R_ARM_GLOB_DAT);
else
@@ -8415,16 +8474,16 @@ Target_arm<big_endian>::Scan::global(Symbol_table* symtab,
{
const bool is_final = gsym->final_value_is_known();
const tls::Tls_optimization optimized_type
- = Target_arm<big_endian>::optimize_tls_reloc(is_final, r_type);
+ = Target_arm<big_endian>::optimize_tls_reloc(is_final, r_type);
switch (r_type)
{
case elfcpp::R_ARM_TLS_GD32: // Global-dynamic
if (optimized_type == tls::TLSOPT_NONE)
{
- // Create a pair of GOT entries for the module index and
- // dtv-relative offset.
- Arm_output_data_got<big_endian>* got
- = target->got_section(symtab, layout);
+ // Create a pair of GOT entries for the module index and
+ // dtv-relative offset.
+ Arm_output_data_got<big_endian>* got
+ = target->got_section(symtab, layout);
if (!parameters->doing_static_link())
got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
target->rel_dyn_section(layout),
@@ -8441,8 +8500,8 @@ Target_arm<big_endian>::Scan::global(Symbol_table* symtab,
case elfcpp::R_ARM_TLS_LDM32: // Local-dynamic
if (optimized_type == tls::TLSOPT_NONE)
{
- // Create a GOT entry for the module index.
- target->got_mod_index_entry(symtab, layout, object);
+ // Create a GOT entry for the module index.
+ target->got_mod_index_entry(symtab, layout, object);
}
else
// FIXME: TLS optimization not supported yet.
@@ -8481,11 +8540,11 @@ Target_arm<big_endian>::Scan::global(Symbol_table* symtab,
layout->set_has_static_tls();
if (parameters->options().shared())
{
- // We need to create a dynamic relocation.
- Reloc_section* rel_dyn = target->rel_dyn_section(layout);
- rel_dyn->add_global(gsym, elfcpp::R_ARM_TLS_TPOFF32,
+ // We need to create a dynamic relocation.
+ Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+ rel_dyn->add_global(gsym, elfcpp::R_ARM_TLS_TPOFF32,
output_section, object,
- data_shndx, reloc.get_r_offset());
+ data_shndx, reloc.get_r_offset());
}
break;
@@ -8604,7 +8663,7 @@ Target_arm<big_endian>::do_finalize_sections(
arm_relobj->attributes_section_data());
merged_any_attributes = true;
}
- }
+ }
for (Input_objects::Dynobj_iterator p = input_objects->dynobj_begin();
p != input_objects->dynobj_end();
@@ -8635,22 +8694,22 @@ Target_arm<big_endian>::do_finalize_sections(
{
// If neither --fix-cortex-a8 nor --no-fix-cortex-a8 is used, turn on
// Cortex-A8 erratum workaround for ARMv7-A or ARMv7 with unknown
- // profile.
+ // profile.
const Object_attribute* cpu_arch_profile_attr =
this->get_aeabi_object_attribute(elfcpp::Tag_CPU_arch_profile);
this->fix_cortex_a8_ =
(cpu_arch_attr->int_value() == elfcpp::TAG_CPU_ARCH_V7
- && (cpu_arch_profile_attr->int_value() == 'A'
- || cpu_arch_profile_attr->int_value() == 0));
+ && (cpu_arch_profile_attr->int_value() == 'A'
+ || cpu_arch_profile_attr->int_value() == 0));
}
-
+
// Check if we can use V4BX interworking.
// The V4BX interworking stub contains BX instruction,
// which is not specified for some profiles.
if (this->fix_v4bx() == General_options::FIX_V4BX_INTERWORKING
&& !this->may_use_v4t_interworking())
gold_error(_("unable to provide V4BX reloc interworking fix up; "
- "the target profile does not support BX instruction"));
+ "the target profile does not support BX instruction"));
// Fill in some more dynamic tags.
const Reloc_section* rel_plt = (this->plt_ == NULL
@@ -8670,21 +8729,21 @@ Target_arm<big_endian>::do_finalize_sections(
if (!parameters->options().relocatable())
{
if (exidx_section != NULL
- && exidx_section->type() == elfcpp::SHT_ARM_EXIDX)
- {
- // For the ARM target, we need to add a PT_ARM_EXIDX segment for
- // the .ARM.exidx section.
- if (!layout->script_options()->saw_phdrs_clause())
- {
- gold_assert(layout->find_output_segment(elfcpp::PT_ARM_EXIDX, 0,
- 0)
- == NULL);
- Output_segment* exidx_segment =
- layout->make_output_segment(elfcpp::PT_ARM_EXIDX, elfcpp::PF_R);
- exidx_segment->add_output_section_to_nonload(exidx_section,
- elfcpp::PF_R);
- }
- }
+ && exidx_section->type() == elfcpp::SHT_ARM_EXIDX)
+ {
+ // For the ARM target, we need to add a PT_ARM_EXIDX segment for
+ // the .ARM.exidx section.
+ if (!layout->script_options()->saw_phdrs_clause())
+ {
+ gold_assert(layout->find_output_segment(elfcpp::PT_ARM_EXIDX, 0,
+ 0)
+ == NULL);
+ Output_segment* exidx_segment =
+ layout->make_output_segment(elfcpp::PT_ARM_EXIDX, elfcpp::PF_R);
+ exidx_segment->add_output_section_to_nonload(exidx_section,
+ elfcpp::PF_R);
+ }
+ }
}
// Create an .ARM.attributes section if we have merged any attributes
@@ -8875,8 +8934,8 @@ Target_arm<big_endian>::Relocate::relocate(
}
else
{
- // This is a local symbol. Determine if the final target is THUMB.
- // We saved this information when all the local symbols were read.
+ // This is a local symbol. Determine if the final target is THUMB.
+ // We saved this information when all the local symbols were read.
elfcpp::Elf_types<32>::Elf_WXword r_info = rel.get_r_info();
unsigned int r_sym = elfcpp::elf_r_sym<32>(r_info);
thumb_bit = object->local_symbol_is_thumb_function(r_sym) ? 1 : 0;
@@ -8892,14 +8951,14 @@ Target_arm<big_endian>::Relocate::relocate(
// Strip LSB if this points to a THUMB target.
if (thumb_bit != 0
- && reloc_property->uses_thumb_bit()
+ && reloc_property->uses_thumb_bit()
&& ((psymval->value(object, 0) & 1) != 0))
{
Arm_address stripped_value =
psymval->value(object, 0) & ~static_cast<Arm_address>(1);
symval.set_output_value(stripped_value);
psymval = &symval;
- }
+ }
// To look up relocation stubs, we need to pass the symbol table index of
// a local symbol.
@@ -8950,9 +9009,9 @@ Target_arm<big_endian>::Relocate::relocate(
relative_address_base = address & 0xfffffffcU;
break;
default:
- gold_unreachable();
+ gold_unreachable();
}
-
+
typename Arm_relocate_functions::Status reloc_status =
Arm_relocate_functions::STATUS_OKAY;
bool check_overflow = reloc_property->checks_overflow();
@@ -9004,7 +9063,7 @@ Target_arm<big_endian>::Relocate::relocate(
case elfcpp::R_ARM_THM_MOVW_ABS_NC:
if (should_apply_static_reloc(gsym, r_type, false, output_section))
reloc_status = Arm_relocate_functions::thm_movw(view, object, psymval,
- 0, thumb_bit, false);
+ 0, thumb_bit, false);
break;
case elfcpp::R_ARM_THM_MOVT_ABS:
@@ -9044,7 +9103,7 @@ Target_arm<big_endian>::Relocate::relocate(
Arm_relocate_functions::thm_movt(view, object, psymval,
relative_address_base);
break;
-
+
case elfcpp::R_ARM_REL32:
reloc_status = Arm_relocate_functions::rel32(view, object, psymval,
address, thumb_bit);
@@ -9113,7 +9172,7 @@ Target_arm<big_endian>::Relocate::relocate(
&& !gsym->is_from_dynobj()
&& !gsym->is_preemptible()));
reloc_status =
- Arm_relocate_functions::arm_branch_common(
+ Arm_relocate_functions::arm_branch_common(
r_type, relinfo, view, gsym, object, r_sym, psymval, address,
thumb_bit, is_weakly_undefined_without_plt);
break;
@@ -9304,50 +9363,50 @@ Target_arm<big_endian>::Relocate::relocate_tls(
switch (r_type)
{
case elfcpp::R_ARM_TLS_GD32: // Global-dynamic
- {
- unsigned int got_type = GOT_TYPE_TLS_PAIR;
- unsigned int got_offset;
- if (gsym != NULL)
- {
- gold_assert(gsym->has_got_offset(got_type));
- got_offset = gsym->got_offset(got_type) - target->got_size();
- }
- else
- {
- unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym, got_type));
- got_offset = (object->local_got_offset(r_sym, got_type)
+ {
+ unsigned int got_type = GOT_TYPE_TLS_PAIR;
+ unsigned int got_offset;
+ if (gsym != NULL)
+ {
+ gold_assert(gsym->has_got_offset(got_type));
+ got_offset = gsym->got_offset(got_type) - target->got_size();
+ }
+ else
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
+ gold_assert(object->local_has_got_offset(r_sym, got_type));
+ got_offset = (object->local_got_offset(r_sym, got_type)
- target->got_size());
- }
- if (optimized_type == tls::TLSOPT_NONE)
- {
+ }
+ if (optimized_type == tls::TLSOPT_NONE)
+ {
Arm_address got_entry =
target->got_plt_section()->address() + got_offset;
-
- // Relocate the field with the PC relative offset of the pair of
- // GOT entries.
+
+ // Relocate the field with the PC relative offset of the pair of
+ // GOT entries.
RelocFuncs::pcrel32_unaligned(view, got_entry, address);
- return ArmRelocFuncs::STATUS_OKAY;
- }
- }
+ return ArmRelocFuncs::STATUS_OKAY;
+ }
+ }
break;
case elfcpp::R_ARM_TLS_LDM32: // Local-dynamic
if (optimized_type == tls::TLSOPT_NONE)
- {
- // Relocate the field with the offset of the GOT entry for
- // the module index.
- unsigned int got_offset;
- got_offset = (target->got_mod_index_entry(NULL, NULL, NULL)
+ {
+ // Relocate the field with the offset of the GOT entry for
+ // the module index.
+ unsigned int got_offset;
+ got_offset = (target->got_mod_index_entry(NULL, NULL, NULL)
- target->got_size());
Arm_address got_entry =
target->got_plt_section()->address() + got_offset;
- // Relocate the field with the PC relative offset of the pair of
- // GOT entries.
- RelocFuncs::pcrel32_unaligned(view, got_entry, address);
+ // Relocate the field with the PC relative offset of the pair of
+ // GOT entries.
+ RelocFuncs::pcrel32_unaligned(view, got_entry, address);
return ArmRelocFuncs::STATUS_OKAY;
- }
+ }
break;
case elfcpp::R_ARM_TLS_LDO32: // Alternate local-dynamic
@@ -9356,51 +9415,51 @@ Target_arm<big_endian>::Relocate::relocate_tls(
case elfcpp::R_ARM_TLS_IE32: // Initial-exec
if (optimized_type == tls::TLSOPT_NONE)
- {
- // Relocate the field with the offset of the GOT entry for
- // the tp-relative offset of the symbol.
+ {
+ // Relocate the field with the offset of the GOT entry for
+ // the tp-relative offset of the symbol.
unsigned int got_type = GOT_TYPE_TLS_OFFSET;
- unsigned int got_offset;
- if (gsym != NULL)
- {
- gold_assert(gsym->has_got_offset(got_type));
- got_offset = gsym->got_offset(got_type);
- }
- else
- {
- unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym, got_type));
- got_offset = object->local_got_offset(r_sym, got_type);
- }
-
- // All GOT offsets are relative to the end of the GOT.
- got_offset -= target->got_size();
+ unsigned int got_offset;
+ if (gsym != NULL)
+ {
+ gold_assert(gsym->has_got_offset(got_type));
+ got_offset = gsym->got_offset(got_type);
+ }
+ else
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
+ gold_assert(object->local_has_got_offset(r_sym, got_type));
+ got_offset = object->local_got_offset(r_sym, got_type);
+ }
+
+ // All GOT offsets are relative to the end of the GOT.
+ got_offset -= target->got_size();
Arm_address got_entry =
target->got_plt_section()->address() + got_offset;
- // Relocate the field with the PC relative offset of the GOT entry.
+ // Relocate the field with the PC relative offset of the GOT entry.
RelocFuncs::pcrel32_unaligned(view, got_entry, address);
return ArmRelocFuncs::STATUS_OKAY;
- }
+ }
break;
case elfcpp::R_ARM_TLS_LE32: // Local-exec
// If we're creating a shared library, a dynamic relocation will
// have been created for this location, so do not apply it now.
if (!parameters->options().shared())
- {
- gold_assert(tls_segment != NULL);
+ {
+ gold_assert(tls_segment != NULL);
// $tp points to the TCB, which is followed by the TLS, so we
// need to add TCB size to the offset.
Arm_address aligned_tcb_size =
align_address(ARM_TCB_SIZE, tls_segment->maximum_alignment());
- RelocFuncs::rel32_unaligned(view, value + aligned_tcb_size);
+ RelocFuncs::rel32_unaligned(view, value + aligned_tcb_size);
- }
+ }
return ArmRelocFuncs::STATUS_OKAY;
-
+
default:
gold_unreachable();
}
@@ -9624,15 +9683,15 @@ Target_arm<big_endian>::relocate_special_relocatable(
Arm_address offset = reloc.get_r_offset();
Arm_address new_offset;
- if (offset_in_output_section != static_cast<off_t>(invalid_address))
+ if (offset_in_output_section != invalid_address)
new_offset = offset + offset_in_output_section;
else
{
section_offset_type sot_offset =
- convert_types<section_offset_type, Arm_address>(offset);
+ convert_types<section_offset_type, Arm_address>(offset);
section_offset_type new_sot_offset =
- output_section->output_offset(object, relinfo->data_shndx,
- sot_offset);
+ output_section->output_offset(object, relinfo->data_shndx,
+ sot_offset);
gold_assert(new_sot_offset != -1);
new_offset = new_sot_offset;
}
@@ -9643,8 +9702,8 @@ Target_arm<big_endian>::relocate_special_relocatable(
if (!parameters->options().relocatable())
{
new_offset += view_address;
- if (offset_in_output_section != static_cast<off_t>(invalid_address))
- new_offset -= offset_in_output_section;
+ if (offset_in_output_section != invalid_address)
+ new_offset -= offset_in_output_section;
}
reloc_write.put_r_offset(new_offset);
@@ -9666,14 +9725,14 @@ Target_arm<big_endian>::relocate_special_relocatable(
Arm_address thumb_bit =
object->local_symbol_is_thumb_function(r_sym) ? 1 : 0;
if (thumb_bit != 0
- && arp->uses_thumb_bit()
+ && arp->uses_thumb_bit()
&& ((psymval->value(object, 0) & 1) != 0))
{
Arm_address stripped_value =
psymval->value(object, 0) & ~static_cast<Arm_address>(1);
symval.set_output_value(stripped_value);
psymval = &symval;
- }
+ }
unsigned char* paddend = view + offset;
typename Arm_relocate_functions<big_endian>::Status reloc_status =
@@ -9731,7 +9790,7 @@ Target_arm<big_endian>::relocate_special_relocatable(
case elfcpp::R_ARM_JUMP24:
case elfcpp::R_ARM_XPC25:
reloc_status =
- Arm_relocate_functions<big_endian>::arm_branch_common(
+ Arm_relocate_functions<big_endian>::arm_branch_common(
r_type, relinfo, paddend, NULL, object, 0, psymval, 0, thumb_bit,
false);
break;
@@ -9992,21 +10051,21 @@ Target_arm<big_endian>::do_make_elf_object(
|| (et == elfcpp::ET_EXEC && input_file->just_symbols()))
{
Arm_relobj<big_endian>* obj =
- new Arm_relobj<big_endian>(name, input_file, offset, ehdr);
+ new Arm_relobj<big_endian>(name, input_file, offset, ehdr);
obj->setup();
return obj;
}
else if (et == elfcpp::ET_DYN)
{
Sized_dynobj<32, big_endian>* obj =
- new Arm_dynobj<big_endian>(name, input_file, offset, ehdr);
+ new Arm_dynobj<big_endian>(name, input_file, offset, ehdr);
obj->setup();
return obj;
}
else
{
gold_error(_("%s: unsupported ELF file type %d"),
- name.c_str(), et);
+ name.c_str(), et);
return NULL;
}
}
@@ -10301,7 +10360,7 @@ Target_arm<big_endian>::tag_cpu_name_value(unsigned int value)
char buffer[100];
sprintf(buffer, "<unknown CPU value %u>", value);
return std::string(buffer);
- }
+ }
}
// Merge object attributes from input file called NAME with those of the
@@ -10331,7 +10390,7 @@ Target_arm<big_endian>::merge_object_attributes(
{
if (out_attr[elfcpp::Tag_MPextension_use].int_value() != 0
&& out_attr[elfcpp::Tag_MPextension_use_legacy].int_value()
- != out_attr[elfcpp::Tag_MPextension_use].int_value())
+ != out_attr[elfcpp::Tag_MPextension_use].int_value())
{
gold_error(_("%s has both the current and legacy "
"Tag_MPextension_use attributes"),
@@ -10361,7 +10420,7 @@ Target_arm<big_endian>::merge_object_attributes(
in_attr[elfcpp::Tag_ABI_VFP_args].int_value());
else if (in_attr[elfcpp::Tag_ABI_FP_number_model].int_value() != 0
&& parameters->options().warn_mismatch())
- gold_error(_("%s uses VFP register arguments, output does not"),
+ gold_error(_("%s uses VFP register arguments, output does not"),
name);
}
@@ -10681,19 +10740,19 @@ Target_arm<big_endian>::merge_object_attributes(
// the input attribute's value is zero or two then if the output
// attribute's value is one the output value is set to the input
// value, otherwise the output value must be the same as the
- // inputs. */
- if (in_attr[i].int_value() != 1 && out_attr[i].int_value() != 1)
- {
+ // inputs. */
+ if (in_attr[i].int_value() != 1 && out_attr[i].int_value() != 1)
+ {
if (in_attr[i].int_value() != out_attr[i].int_value())
{
gold_error(_("DIV usage mismatch between %s and output"),
name);
}
- }
+ }
if (in_attr[i].int_value() != 1)
- out_attr[i].set_int_value(in_attr[i].int_value());
-
+ out_attr[i].set_int_value(in_attr[i].int_value());
+
break;
case elfcpp::Tag_MPextension_use_legacy:
@@ -10706,7 +10765,7 @@ Target_arm<big_endian>::merge_object_attributes(
!= in_attr[i].int_value())
{
gold_error(_("%s has has both the current and legacy "
- "Tag_MPextension_use attributes"),
+ "Tag_MPextension_use attributes"),
name);
}
}
@@ -10802,7 +10861,7 @@ Target_arm<big_endian>::merge_object_attributes(
err_tag = out_iter->first;
int saved_tag = out_iter->first;
delete out_iter->second;
- out_other_attributes->erase(out_iter);
+ out_other_attributes->erase(out_iter);
out_iter = out_other_attributes->upper_bound(saved_tag);
}
else if (in_iter != in_other_attributes->end()
@@ -10880,7 +10939,7 @@ Target_arm<big_endian>::new_arm_input_section(
// for this input section already.
gold_assert(ins.second);
- return arm_input_section;
+ return arm_input_section;
}
// Find the Arm_input_section object corresponding to the SHNDX-th input
@@ -10975,7 +11034,7 @@ Target_arm<big_endian>::scan_reloc_for_stub(
psymval->value(arm_relobj, 0) & ~static_cast<Arm_address>(1);
symval.set_output_value(stripped_value);
psymval = &symval;
- }
+ }
// Get the symbol value.
Symbol_value<32>::Value value = psymval->value(arm_relobj, 0);
@@ -11009,10 +11068,10 @@ Target_arm<big_endian>::scan_reloc_for_stub(
if (stub_type != arm_stub_none)
{
// Try looking up an existing stub from a stub table.
- Stub_table<big_endian>* stub_table =
+ Stub_table<big_endian>* stub_table =
arm_relobj->stub_table(relinfo->data_shndx);
gold_assert(stub_table != NULL);
-
+
// Locate stub by destination.
Reloc_stub::Key stub_key(stub_type, gsym, arm_relobj, r_sym, addend);
@@ -11100,13 +11159,13 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs(
// Only a few relocation types need stubs.
if ((r_type != elfcpp::R_ARM_CALL)
- && (r_type != elfcpp::R_ARM_JUMP24)
- && (r_type != elfcpp::R_ARM_PLT32)
- && (r_type != elfcpp::R_ARM_THM_CALL)
- && (r_type != elfcpp::R_ARM_THM_XPC22)
- && (r_type != elfcpp::R_ARM_THM_JUMP24)
- && (r_type != elfcpp::R_ARM_THM_JUMP19)
- && (r_type != elfcpp::R_ARM_V4BX))
+ && (r_type != elfcpp::R_ARM_JUMP24)
+ && (r_type != elfcpp::R_ARM_PLT32)
+ && (r_type != elfcpp::R_ARM_THM_CALL)
+ && (r_type != elfcpp::R_ARM_THM_XPC22)
+ && (r_type != elfcpp::R_ARM_THM_JUMP24)
+ && (r_type != elfcpp::R_ARM_THM_JUMP19)
+ && (r_type != elfcpp::R_ARM_V4BX))
continue;
section_offset_type offset =
@@ -11145,7 +11204,7 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs(
{
// create a new stub and add it to stub table.
Arm_v4bx_stub* stub =
- this->stub_factory().make_arm_v4bx_stub(reg);
+ this->stub_factory().make_arm_v4bx_stub(reg);
gold_assert(stub != NULL);
stub_table->add_arm_v4bx_stub(stub);
}
@@ -11170,11 +11229,11 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs(
sym = NULL;
psymval = arm_object->local_symbol(r_sym);
- // If the local symbol belongs to a section we are discarding,
- // and that section is a debug section, try to find the
- // corresponding kept section and map this symbol to its
- // counterpart in the kept section. The symbol must not
- // correspond to a section we are folding.
+ // If the local symbol belongs to a section we are discarding,
+ // and that section is a debug section, try to find the
+ // corresponding kept section and map this symbol to its
+ // counterpart in the kept section. The symbol must not
+ // correspond to a section we are folding.
bool is_ordinary;
shndx = psymval->input_shndx(&is_ordinary);
is_defined_in_discarded_section =
@@ -11190,7 +11249,7 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs(
typedef Sized_relobj_file<32, big_endian> ObjType;
typename ObjType::Compute_final_local_value_status status =
arm_object->compute_final_local_value(r_sym, psymval, &symval,
- relinfo->symtab);
+ relinfo->symtab);
if (status == ObjType::CFLV_OK)
{
// Currently we cannot handle a branch to a target in
@@ -11209,7 +11268,7 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs(
else
{
// We cannot determine the final value.
- continue;
+ continue;
}
}
}
@@ -11430,7 +11489,7 @@ Target_arm<big_endian>::do_relax(
}
group_sections(layout, stub_group_size, stubs_always_after_branch, task);
-
+
// Also fix .ARM.exidx section coverage.
Arm_output_section<big_endian>* exidx_output_section = NULL;
for (Layout::Section_list::const_iterator p =
@@ -11494,7 +11553,7 @@ Target_arm<big_endian>::do_relax(
++sp)
(*sp)->remove_all_cortex_a8_stubs();
}
-
+
// Scan relocs for relocation stubs
for (Input_objects::Relobj_iterator op = input_objects->relobj_begin();
op != input_objects->relobj_end();
@@ -11710,16 +11769,16 @@ Target_arm<big_endian>::scan_span_for_cortex_a8_erratum(
// Encoding T4: B<c>.W.
is_b = (insn & 0xf800d000U) == 0xf0009000U;
// Encoding T1: BL<c>.W.
- is_bl = (insn & 0xf800d000U) == 0xf000d000U;
- // Encoding T2: BLX<c>.W.
- is_blx = (insn & 0xf800d000U) == 0xf000c000U;
+ is_bl = (insn & 0xf800d000U) == 0xf000d000U;
+ // Encoding T2: BLX<c>.W.
+ is_blx = (insn & 0xf800d000U) == 0xf000c000U;
// Encoding T3: B<c>.W (not permitted in IT block).
is_bcc = ((insn & 0xf800d000U) == 0xf0008000U
&& (insn & 0x07f00000U) != 0x03800000U);
}
bool is_32bit_branch = is_b || is_bl || is_blx || is_bcc;
-
+
// If this instruction is a 32-bit THUMB branch that crosses a 4K
// page boundary and it follows 32-bit non-branch instruction,
// we need to work around.
@@ -11754,7 +11813,7 @@ Target_arm<big_endian>::scan_span_for_cortex_a8_erratum(
// Check if we have an offending branch instruction.
uint16_t upper_insn = (insn >> 16) & 0xffffU;
uint16_t lower_insn = insn & 0xffffU;
- typedef struct Arm_relocate_functions<big_endian> RelocFuncs;
+ typedef class Arm_relocate_functions<big_endian> RelocFuncs;
if (cortex_a8_reloc != NULL
&& cortex_a8_reloc->reloc_stub() != NULL)
@@ -11774,7 +11833,7 @@ Target_arm<big_endian>::scan_span_for_cortex_a8_erratum(
offset = RelocFuncs::thumb32_branch_offset(upper_insn,
lower_insn);
if (is_blx)
- offset &= ~3;
+ offset &= ~3;
stub_type = (is_blx
? arm_stub_a8_veneer_blx
@@ -11811,17 +11870,17 @@ Target_arm<big_endian>::scan_span_for_cortex_a8_erratum(
if (is_blx)
pc_for_insn &= ~3;
- // If we found a relocation, use the proper destination,
+ // If we found a relocation, use the proper destination,
// not the offset in the (unrelocated) instruction.
// Note this is always done if we switched the stub type above.
- if (cortex_a8_reloc != NULL)
- offset = (off_t) (cortex_a8_reloc->destination() - pc_for_insn);
+ if (cortex_a8_reloc != NULL)
+ offset = (off_t) (cortex_a8_reloc->destination() - pc_for_insn);
- Arm_address target = (pc_for_insn + offset) | (is_blx ? 0 : 1);
+ Arm_address target = (pc_for_insn + offset) | (is_blx ? 0 : 1);
// Add a new stub if destination address in in the same page.
- if (((address + i) & ~0xfffU) == (target & ~0xfffU))
- {
+ if (((address + i) & ~0xfffU) == (target & ~0xfffU))
+ {
Cortex_a8_stub* stub =
this->stub_factory_.make_cortex_a8_stub(stub_type,
arm_relobj, shndx,
@@ -11831,9 +11890,9 @@ Target_arm<big_endian>::scan_span_for_cortex_a8_erratum(
arm_relobj->stub_table(shndx);
gold_assert(stub_table != NULL);
stub_table->add_cortex_a8_stub(address + i, stub);
- }
- }
- }
+ }
+ }
+ }
i += insn_32bit ? 4 : 2;
last_was_32bit = insn_32bit;
@@ -11857,7 +11916,7 @@ Target_arm<big_endian>::apply_cortex_a8_workaround(
Valtype lower_insn = elfcpp::Swap<16, big_endian>::readval(wv + 1);
off_t branch_offset = stub_address - (insn_address + 4);
- typedef struct Arm_relocate_functions<big_endian> RelocFuncs;
+ typedef class Arm_relocate_functions<big_endian> RelocFuncs;
switch (stub->stub_template()->type())
{
case arm_stub_a8_veneer_b_cond:
@@ -11877,7 +11936,7 @@ Target_arm<big_endian>::apply_cortex_a8_workaround(
branch_offset = (branch_offset + 2) & ~3;
// Put BRANCH_OFFSET back into the insn.
- gold_assert(!utils::has_overflow<25>(branch_offset));
+ gold_assert(!Bits<25>::has_overflow32(branch_offset));
upper_insn = RelocFuncs::thumb32_branch_upper(upper_insn, branch_offset);
lower_insn = RelocFuncs::thumb32_branch_lower(lower_insn, branch_offset);
break;
@@ -11891,6 +11950,9 @@ Target_arm<big_endian>::apply_cortex_a8_workaround(
elfcpp::Swap<16, big_endian>::writeval(wv + 1, lower_insn);
}
+// Target selector for ARM. Note this is never instantiated directly.
+// It's only used in Target_selector_arm_nacl, below.
+
template<bool big_endian>
class Target_selector_arm : public Target_selector
{
@@ -11964,7 +12026,7 @@ Target_arm<big_endian>::fix_exidx_coverage(
Arm_output_section<big_endian>* arm_output_section =
Arm_output_section<big_endian>::as_arm_output_section(*p);
arm_output_section->append_text_sections_to_list(&sorted_text_sections);
- }
+ }
exidx_section->fix_exidx_coverage(layout, sorted_text_sections, symtab,
merge_exidx_entries(), task);
@@ -12025,7 +12087,217 @@ Target_arm<big_endian>::do_define_standard_symbols(
}
}
-Target_selector_arm<false> target_selector_arm;
-Target_selector_arm<true> target_selector_armbe;
+// NaCl variant. It uses different PLT contents.
+
+template<bool big_endian>
+class Output_data_plt_arm_nacl;
+
+template<bool big_endian>
+class Target_arm_nacl : public Target_arm<big_endian>
+{
+ public:
+ Target_arm_nacl()
+ : Target_arm<big_endian>(&arm_nacl_info)
+ { }
+
+ protected:
+ virtual Output_data_plt_arm<big_endian>*
+ do_make_data_plt(Layout* layout, Output_data_space* got_plt)
+ { return new Output_data_plt_arm_nacl<big_endian>(layout, got_plt); }
+
+ private:
+ static const Target::Target_info arm_nacl_info;
+};
+
+template<bool big_endian>
+const Target::Target_info Target_arm_nacl<big_endian>::arm_nacl_info =
+{
+ 32, // size
+ big_endian, // is_big_endian
+ elfcpp::EM_ARM, // machine_code
+ false, // has_make_symbol
+ false, // has_resolve
+ false, // has_code_fill
+ true, // is_default_stack_executable
+ false, // can_icf_inline_merge_sections
+ '\0', // wrap_char
+ "/lib/ld-nacl-arm.so.1", // dynamic_linker
+ 0x20000, // default_text_segment_address
+ 0x10000, // abi_pagesize (overridable by -z max-page-size)
+ 0x10000, // common_pagesize (overridable by -z common-page-size)
+ true, // isolate_execinstr
+ 0x10000000, // rosegment_gap
+ elfcpp::SHN_UNDEF, // small_common_shndx
+ elfcpp::SHN_UNDEF, // large_common_shndx
+ 0, // small_common_section_flags
+ 0, // large_common_section_flags
+ ".ARM.attributes", // attributes_section
+ "aeabi" // attributes_vendor
+};
+
+template<bool big_endian>
+class Output_data_plt_arm_nacl : public Output_data_plt_arm<big_endian>
+{
+ public:
+ Output_data_plt_arm_nacl(Layout* layout, Output_data_space* got_plt)
+ : Output_data_plt_arm<big_endian>(layout, 16, got_plt)
+ { }
+
+ protected:
+ // Return the offset of the first non-reserved PLT entry.
+ virtual unsigned int
+ do_first_plt_entry_offset() const
+ { return sizeof(first_plt_entry); }
+
+ // Return the size of a PLT entry.
+ virtual unsigned int
+ do_get_plt_entry_size() const
+ { return sizeof(plt_entry); }
+
+ virtual void
+ do_fill_first_plt_entry(unsigned char* pov,
+ Arm_address got_address,
+ Arm_address plt_address);
+
+ virtual void
+ do_fill_plt_entry(unsigned char* pov,
+ Arm_address got_address,
+ Arm_address plt_address,
+ unsigned int got_offset,
+ unsigned int plt_offset);
+
+ private:
+ inline uint32_t arm_movw_immediate(uint32_t value)
+ {
+ return (value & 0x00000fff) | ((value & 0x0000f000) << 4);
+ }
+
+ inline uint32_t arm_movt_immediate(uint32_t value)
+ {
+ return ((value & 0x0fff0000) >> 16) | ((value & 0xf0000000) >> 12);
+ }
+
+ // Template for the first PLT entry.
+ static const uint32_t first_plt_entry[16];
+
+ // Template for subsequent PLT entries.
+ static const uint32_t plt_entry[4];
+};
+
+// The first entry in the PLT.
+template<bool big_endian>
+const uint32_t Output_data_plt_arm_nacl<big_endian>::first_plt_entry[16] =
+{
+ // First bundle:
+ 0xe300c000, // movw ip, #:lower16:&GOT[2]-.+8
+ 0xe340c000, // movt ip, #:upper16:&GOT[2]-.+8
+ 0xe08cc00f, // add ip, ip, pc
+ 0xe52dc008, // str ip, [sp, #-8]!
+ // Second bundle:
+ 0xe7dfcf1f, // bfc ip, #30, #2
+ 0xe59cc000, // ldr ip, [ip]
+ 0xe3ccc13f, // bic ip, ip, #0xc000000f
+ 0xe12fff1c, // bx ip
+ // Third bundle:
+ 0xe320f000, // nop
+ 0xe320f000, // nop
+ 0xe320f000, // nop
+ // .Lplt_tail:
+ 0xe50dc004, // str ip, [sp, #-4]
+ // Fourth bundle:
+ 0xe7dfcf1f, // bfc ip, #30, #2
+ 0xe59cc000, // ldr ip, [ip]
+ 0xe3ccc13f, // bic ip, ip, #0xc000000f
+ 0xe12fff1c, // bx ip
+};
+
+template<bool big_endian>
+void
+Output_data_plt_arm_nacl<big_endian>::do_fill_first_plt_entry(
+ unsigned char* pov,
+ Arm_address got_address,
+ Arm_address plt_address)
+{
+ // Write first PLT entry. All but first two words are constants.
+ const size_t num_first_plt_words = (sizeof(first_plt_entry)
+ / sizeof(first_plt_entry[0]));
+
+ int32_t got_displacement = got_address + 8 - (plt_address + 16);
+
+ elfcpp::Swap<32, big_endian>::writeval
+ (pov + 0, first_plt_entry[0] | arm_movw_immediate (got_displacement));
+ elfcpp::Swap<32, big_endian>::writeval
+ (pov + 4, first_plt_entry[1] | arm_movt_immediate (got_displacement));
+
+ for (size_t i = 2; i < num_first_plt_words; ++i)
+ elfcpp::Swap<32, big_endian>::writeval(pov + i * 4, first_plt_entry[i]);
+}
+
+// Subsequent entries in the PLT.
+
+template<bool big_endian>
+const uint32_t Output_data_plt_arm_nacl<big_endian>::plt_entry[4] =
+{
+ 0xe300c000, // movw ip, #:lower16:&GOT[n]-.+8
+ 0xe340c000, // movt ip, #:upper16:&GOT[n]-.+8
+ 0xe08cc00f, // add ip, ip, pc
+ 0xea000000, // b .Lplt_tail
+};
+
+template<bool big_endian>
+void
+Output_data_plt_arm_nacl<big_endian>::do_fill_plt_entry(
+ unsigned char* pov,
+ Arm_address got_address,
+ Arm_address plt_address,
+ unsigned int got_offset,
+ unsigned int plt_offset)
+{
+ // Calculate the displacement between the PLT slot and the
+ // common tail that's part of the special initial PLT slot.
+ int32_t tail_displacement = (plt_address + (11 * sizeof(uint32_t))
+ - (plt_address + plt_offset
+ + sizeof(plt_entry) + sizeof(uint32_t)));
+ gold_assert((tail_displacement & 3) == 0);
+ tail_displacement >>= 2;
+
+ gold_assert ((tail_displacement & 0xff000000) == 0
+ || (-tail_displacement & 0xff000000) == 0);
+
+ // Calculate the displacement between the PLT slot and the entry
+ // in the GOT. The offset accounts for the value produced by
+ // adding to pc in the penultimate instruction of the PLT stub.
+ const int32_t got_displacement = (got_address + got_offset
+ - (plt_address + sizeof(plt_entry)));
+
+ elfcpp::Swap<32, big_endian>::writeval
+ (pov + 0, plt_entry[0] | arm_movw_immediate (got_displacement));
+ elfcpp::Swap<32, big_endian>::writeval
+ (pov + 4, plt_entry[1] | arm_movt_immediate (got_displacement));
+ elfcpp::Swap<32, big_endian>::writeval
+ (pov + 8, plt_entry[2]);
+ elfcpp::Swap<32, big_endian>::writeval
+ (pov + 12, plt_entry[3] | (tail_displacement & 0x00ffffff));
+}
+
+// Target selectors.
+
+template<bool big_endian>
+class Target_selector_arm_nacl
+ : public Target_selector_nacl<Target_selector_arm<big_endian>,
+ Target_arm_nacl<big_endian> >
+{
+ public:
+ Target_selector_arm_nacl()
+ : Target_selector_nacl<Target_selector_arm<big_endian>,
+ Target_arm_nacl<big_endian> >(
+ "arm",
+ big_endian ? "elf32-bigarm-nacl" : "elf32-littlearm-nacl",
+ big_endian ? "armelfb_nacl" : "armelf_nacl")
+ { }
+};
+
+Target_selector_arm_nacl<false> target_selector_arm;
+Target_selector_arm_nacl<true> target_selector_armbe;
} // End anonymous namespace.
diff --git a/binutils-2.22/gold/common.cc b/binutils-2.22/gold/common.cc
index 1a9aea8..b0c7d6e 100644
--- a/binutils-2.22/gold/common.cc
+++ b/binutils-2.22/gold/common.cc
@@ -1,6 +1,7 @@
// common.cc -- handle common symbols for gold
-// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -222,9 +223,6 @@ Symbol_table::do_allocate_commons_list(
Mapfile* mapfile,
Sort_commons_order sort_order)
{
- typedef typename Sized_symbol<size>::Value_type Value_type;
- typedef typename Sized_symbol<size>::Size_type Size_type;
-
// We've kept a list of all the common symbols. But the symbol may
// have been resolved to a defined symbol by now. And it may be a
// forwarder. First remove all non-common symbols.
diff --git a/binutils-2.22/gold/config.in b/binutils-2.22/gold/config.in
index 8611376..3edc0d6 100644
--- a/binutils-2.22/gold/config.in
+++ b/binutils-2.22/gold/config.in
@@ -1,5 +1,12 @@
/* config.in. Generated from configure.ac by autoheader. */
+/* Check that config.h is #included before system headers
+ (this works only for glibc, but that should be enough). */
+#if defined(__GLIBC__) && !defined(__CONFIG_H__)
+# error config.h must be #included before system headers
+#endif
+#define __CONFIG_H__ 1
+
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
@@ -72,6 +79,9 @@
/* Define to 1 if you have the <ext/hash_set> header file. */
#undef HAVE_EXT_HASH_SET
+/* Define to 1 if you have the `fallocate' function. */
+#undef HAVE_FALLOCATE
+
/* Define to 1 if you have the `ffsll' function. */
#undef HAVE_FFSLL
@@ -81,6 +91,12 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
+/* Define if your <locale.h> file defines LC_MESSAGES. */
+#undef HAVE_LC_MESSAGES
+
+/* Define to 1 if you have the <locale.h> header file. */
+#undef HAVE_LOCALE_H
+
/* Define to 1 if you have the `mallinfo' function. */
#undef HAVE_MALLINFO
@@ -105,6 +121,9 @@
/* Define to 1 if you have the `readv' function. */
#undef HAVE_READV
+/* Define to 1 if you have the `setlocale' function. */
+#undef HAVE_SETLOCALE
+
/* Define if struct stat has a field st_mtim with timespec for mtime */
#undef HAVE_STAT_ST_MTIM
@@ -150,6 +169,9 @@
/* Define to 1 if you have the `times' function. */
#undef HAVE_TIMES
+/* Define if std::tr1::hash<off_t> is usable */
+#undef HAVE_TR1_HASH_OFF_T
+
/* Define to 1 if you have the <tr1/unordered_map> header file. */
#undef HAVE_TR1_UNORDERED_MAP
@@ -165,6 +187,12 @@
/* Define to 1 if you have the <zlib.h> header file. */
#undef HAVE_ZLIB_H
+/* Default library search path */
+#undef LIB_PATH
+
+/* Whether configured as a native linker */
+#undef NATIVE_LINKER
+
/* Name of package */
#undef PACKAGE
diff --git a/binutils-2.22/gold/configure b/binutils-2.22/gold/configure
index e0a91f8..0bffe08 100755
--- a/binutils-2.22/gold/configure
+++ b/binutils-2.22/gold/configure
@@ -594,11 +594,15 @@ LTLIBOBJS
MAINT
MAINTAINER_MODE_FALSE
MAINTAINER_MODE_TRUE
+HAVE_PUBNAMES_FALSE
+HAVE_PUBNAMES_TRUE
CXXCPP
HAVE_ZLIB_FALSE
HAVE_ZLIB_TRUE
LIBOBJS
LFS_CFLAGS
+GOLD_LDADD
+GOLD_LDFLAGS
WARN_CXXFLAGS
NO_WERROR
WARN_CFLAGS
@@ -773,10 +777,13 @@ enable_gold
enable_threads
enable_plugins
enable_targets
+with_lib_path
enable_dependency_tracking
enable_nls
enable_werror
enable_build_warnings
+with_gold_ldflags
+with_gold_ldadd
enable_maintainer_mode
'
ac_precious_vars='build_alias
@@ -1431,6 +1438,9 @@ Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--with-sysroot=DIR search for usr/lib et al within DIR
+ --with-lib-path=dir1:dir2... set default LIB_PATH
+ --with-gold-ldflags=FLAGS additional link flags for gold
+ --with-gold-ldadd=LIBS additional libraries for gold
Some influential environment variables:
CC C compiler command
@@ -3214,6 +3224,9 @@ am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
ac_config_headers="$ac_config_headers config.h:config.in"
+# PR 14072
+
+
# Check whether --with-sysroot was given.
if test "${with_sysroot+set}" = set; then :
@@ -3529,6 +3542,29 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+
+# Check whether --with-lib-path was given.
+if test "${with_lib_path+set}" = set; then :
+ withval=$with_lib_path; case "$withval" in
+ yes) LIB_PATH='"/lib:/usr/lib"' ;;
+ no) LIB_PATH='""' ;;
+ *) LIB_PATH='"'"$withval"'"' ;;
+ esac
+else
+ LIB_PATH='"::DEFAULT::"'
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define LIB_PATH $LIB_PATH
+_ACEOF
+
+if test "x$target_alias" = "x" -o "x$host_alias" = "x$target_alias"; then
+
+$as_echo "#define NATIVE_LINKER 1" >>confdefs.h
+
+fi
+
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}nm", so it can be a program name with args.
set dummy ${ac_tool_prefix}nm; ac_word=$2
@@ -6281,7 +6317,20 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gold_cv_prog_gcc41" >&5
$as_echo "$gold_cv_prog_gcc41" >&6; }
- if test "$target_cpu" = "x86_64" -a "$gold_cv_prog_gcc41" = "yes"; then
+save_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -mcmodel=medium"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int i;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ have_mcmodel_medium=yes
+else
+ have_mcmodel_medium=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+CFLAGS="$save_CFLAGS"
+ if test "$target_cpu" = "x86_64" -a "$have_mcmodel_medium" = "yes" -a "$gold_cv_prog_gcc41" = "yes"; then
MCMODEL_MEDIUM_TRUE=
MCMODEL_MEDIUM_FALSE='#'
else
@@ -6393,10 +6442,16 @@ fi
save_CFLAGS="$CFLAGS"
-CFLAGS="$CFLAGS -mtls-dialect=gnu2"
+CFLAGS="$CFLAGS -fpic -mtls-dialect=gnu2"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-int i;
+
+__thread int i;
+void foo (void)
+{
+ i = 10;
+}
+
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
have_tls_gnu2=yes
@@ -6619,6 +6674,34 @@ fi
WARN_CXXFLAGS=`echo ${WARN_CFLAGS} | sed -e 's/-Wstrict-prototypes//' -e 's/-Wmissing-prototypes//' -e 's/-Wshadow//'`
+
+# Check whether --with-gold-ldflags was given.
+if test "${with_gold_ldflags+set}" = set; then :
+ withval=$with_gold_ldflags; if test "$withval" = "no" -o "$withval" = "yes"; then
+ GOLD_LDFLAGS=
+ else
+ GOLD_LDFLAGS=$withval
+ fi
+else
+ GOLD_LDFLAGS=
+fi
+
+
+
+
+# Check whether --with-gold-ldadd was given.
+if test "${with_gold_ldadd+set}" = set; then :
+ withval=$with_gold_ldadd; if test "$withval" = "no" -o "$withval" = "yes"; then
+ GOLD_LDADD=
+ else
+ GOLD_LDADD=$withval
+ fi
+else
+ GOLD_LDADD=
+fi
+
+
+
LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
@@ -7043,7 +7126,7 @@ fi
done
-for ac_func in mallinfo posix_fallocate readv sysconf times
+for ac_func in mallinfo posix_fallocate fallocate readv sysconf times
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -7185,6 +7268,39 @@ $as_echo "#define HAVE_TR1_UNORDERED_MAP_REHASH 1" >>confdefs.h
fi
+# Use of tr1/unordered_map with off_t as a key is not supported on GCC
+# 4.1.xx when compiling in 32-bit mode with a 64-bit off_t type.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether std::tr1::hash<off_t> is defined" >&5
+$as_echo_n "checking whether std::tr1::hash<off_t> is defined... " >&6; }
+if test "${gold_cv_hash_off_t+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ CXXFLAGS_hold=$CXXFLAGS
+CXXFLAGS="$CXXFLAGS $LFS_CFLAGS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <tr1/unordered_map>
+std::tr1::hash<off_t> h;
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ gold_cv_hash_off_t=yes
+else
+ gold_cv_hash_off_t=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+CXXFLAGS=$CFLAGS_hold
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gold_cv_hash_off_t" >&5
+$as_echo "$gold_cv_hash_off_t" >&6; }
+if test "$gold_cv_hash_off_t" = "yes"; then
+
+$as_echo "#define HAVE_TR1_HASH_OFF_T 1" >>confdefs.h
+
+fi
+
# gcc 4.3.0 doesn't recognize the printf attribute on a template
# function. Check for that. This is gcc bug 35546. This test can
# probably be removed after the bug has been fixed for a while.
@@ -7251,6 +7367,28 @@ $as_echo "#define HAVE_STAT_ST_MTIM 1" >>confdefs.h
fi
+save_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS -gpubnames"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int i;
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ have_pubnames=yes
+else
+ have_pubnames=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+CXXFLAGS="$save_CXXFLAGS"
+ if test "$have_pubnames" = "yes"; then
+ HAVE_PUBNAMES_TRUE=
+ HAVE_PUBNAMES_FALSE='#'
+else
+ HAVE_PUBNAMES_TRUE='#'
+ HAVE_PUBNAMES_FALSE=
+fi
+
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -7258,6 +7396,63 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
+for ac_header in locale.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "locale.h" "ac_cv_header_locale_h" "$ac_includes_default"
+if test "x$ac_cv_header_locale_h" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LOCALE_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_func in setlocale
+do :
+ ac_fn_c_check_func "$LINENO" "setlocale" "ac_cv_func_setlocale"
+if test "x$ac_cv_func_setlocale" = x""yes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SETLOCALE 1
+_ACEOF
+
+fi
+done
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LC_MESSAGES" >&5
+$as_echo_n "checking for LC_MESSAGES... " >&6; }
+if test "${am_cv_val_LC_MESSAGES+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <locale.h>
+int
+main ()
+{
+return LC_MESSAGES
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ am_cv_val_LC_MESSAGES=yes
+else
+ am_cv_val_LC_MESSAGES=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_val_LC_MESSAGES" >&5
+$as_echo "$am_cv_val_LC_MESSAGES" >&6; }
+ if test $am_cv_val_LC_MESSAGES = yes; then
+
+$as_echo "#define HAVE_LC_MESSAGES 1" >>confdefs.h
+
+ fi
+
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
@@ -7486,6 +7681,10 @@ if test -z "${HAVE_ZLIB_TRUE}" && test -z "${HAVE_ZLIB_FALSE}"; then
as_fn_error "conditional \"HAVE_ZLIB\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${HAVE_PUBNAMES_TRUE}" && test -z "${HAVE_PUBNAMES_FALSE}"; then
+ as_fn_error "conditional \"HAVE_PUBNAMES\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
as_fn_error "conditional \"MAINTAINER_MODE\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
diff --git a/binutils-2.22/gold/configure.ac b/binutils-2.22/gold/configure.ac
index 685e85b..05e807b 100644
--- a/binutils-2.22/gold/configure.ac
+++ b/binutils-2.22/gold/configure.ac
@@ -11,6 +11,15 @@ AM_INIT_AUTOMAKE([no-dist parallel-tests])
AM_CONFIG_HEADER(config.h:config.in)
+# PR 14072
+AH_VERBATIM([00_CONFIG_H_CHECK],
+[/* Check that config.h is #included before system headers
+ (this works only for glibc, but that should be enough). */
+#if defined(__GLIBC__) && !defined(__CONFIG_H__)
+# error config.h must be #included before system headers
+#endif
+#define __CONFIG_H__ 1])
+
AC_ARG_WITH(sysroot,
[ --with-sysroot[=DIR] search for usr/lib et al within DIR],
[sysroot=$withval], [sysroot=no])
@@ -45,7 +54,7 @@ dnl "installed_linker" is the installed gold linker name.
default_ld=
AC_ARG_ENABLE(ld,
[[ --enable-ld[=ARG] build ld [ARG={default,yes,no}]]],
-[case "${enableval}" in
+[case "${enableval}" in
default)
default_ld=ld.bfd
;;
@@ -238,6 +247,20 @@ AC_DEFINE_UNQUOTED(GOLD_DEFAULT_BIG_ENDIAN, $default_big_endian,
AC_DEFINE_UNQUOTED(GOLD_DEFAULT_OSABI, $default_osabi,
[Default OSABI code])
+AC_ARG_WITH(lib-path,
+[ --with-lib-path=dir1:dir2... set default LIB_PATH],
+[case "$withval" in
+ yes) LIB_PATH='"/lib:/usr/lib"' ;;
+ no) LIB_PATH='""' ;;
+ *) LIB_PATH='"'"$withval"'"' ;;
+ esac],
+[LIB_PATH='"::DEFAULT::"'])
+AC_DEFINE_UNQUOTED(LIB_PATH, $LIB_PATH,
+ [Default library search path])
+if test "x$target_alias" = "x" -o "x$host_alias" = "x$target_alias"; then
+ AC_DEFINE(NATIVE_LINKER, 1, [Whether configured as a native linker])
+fi
+
AC_CHECK_TOOL(NM, nm)
AC_PROG_CC
@@ -298,9 +321,13 @@ error
#endif
], [gold_cv_prog_gcc41=yes], [gold_cv_prog_gcc41=no])])
+save_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -mcmodel=medium"
+AC_COMPILE_IFELSE([int i;], [have_mcmodel_medium=yes], [have_mcmodel_medium=no])
+CFLAGS="$save_CFLAGS"
dnl Whether we can test -mcmodel=medium.
AM_CONDITIONAL(MCMODEL_MEDIUM,
-[test "$target_cpu" = "x86_64" -a "$gold_cv_prog_gcc41" = "yes"])
+[test "$target_cpu" = "x86_64" -a "$have_mcmodel_medium" = "yes" -a "$gold_cv_prog_gcc41" = "yes"])
dnl Test for __thread support.
AC_CACHE_CHECK([for thread support], [gold_cv_c_thread],
@@ -341,8 +368,14 @@ AM_CONDITIONAL(OMP_SUPPORT, test "$gold_cv_c_threadprivate" = "yes")
dnl Test for the -ftls-dialect=gnu2 option.
save_CFLAGS="$CFLAGS"
-CFLAGS="$CFLAGS -mtls-dialect=gnu2"
-AC_COMPILE_IFELSE([int i;], [have_tls_gnu2=yes], [have_tls_gnu2=no])
+CFLAGS="$CFLAGS -fpic -mtls-dialect=gnu2"
+AC_COMPILE_IFELSE([
+__thread int i;
+void foo (void)
+{
+ i = 10;
+}
+], [have_tls_gnu2=yes], [have_tls_gnu2=no])
CFLAGS="$save_CFLAGS"
AM_CONDITIONAL(TLS_GNU2_DIALECT, test "$have_tls_gnu2" = "yes")
@@ -409,6 +442,26 @@ AM_BINUTILS_WARNINGS
WARN_CXXFLAGS=`echo ${WARN_CFLAGS} | sed -e 's/-Wstrict-prototypes//' -e 's/-Wmissing-prototypes//' -e 's/-Wshadow//'`
AC_SUBST(WARN_CXXFLAGS)
+AC_ARG_WITH(gold-ldflags,
+[ --with-gold-ldflags=FLAGS additional link flags for gold],
+[if test "$withval" = "no" -o "$withval" = "yes"; then
+ GOLD_LDFLAGS=
+ else
+ GOLD_LDFLAGS=$withval
+ fi],
+[GOLD_LDFLAGS=])
+AC_SUBST(GOLD_LDFLAGS)
+
+AC_ARG_WITH(gold-ldadd,
+[ --with-gold-ldadd=LIBS additional libraries for gold],
+[if test "$withval" = "no" -o "$withval" = "yes"; then
+ GOLD_LDADD=
+ else
+ GOLD_LDADD=$withval
+ fi],
+[GOLD_LDADD=])
+AC_SUBST(GOLD_LDADD)
+
dnl Force support for large files by default. This may need to be
dnl host dependent. If build == host, we can check getconf LFS_CFLAGS.
LFS_CFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
@@ -446,7 +499,7 @@ AC_LANG_PUSH(C++)
AC_CHECK_HEADERS(tr1/unordered_set tr1/unordered_map)
AC_CHECK_HEADERS(ext/hash_map ext/hash_set)
AC_CHECK_HEADERS(byteswap.h)
-AC_CHECK_FUNCS(mallinfo posix_fallocate readv sysconf times)
+AC_CHECK_FUNCS(mallinfo posix_fallocate fallocate readv sysconf times)
AC_CHECK_DECLS([basename, ffs, asprintf, vasprintf, snprintf, vsnprintf, strverscmp, strndup, memmem])
# Use of ::std::tr1::unordered_map::rehash causes undefined symbols
@@ -462,6 +515,25 @@ if test "$gold_cv_unordered_map_rehash" = "yes"; then
[Define if ::std::tr1::unordered_map::rehash is usable])
fi
+# Use of tr1/unordered_map with off_t as a key is not supported on GCC
+# 4.1.xx when compiling in 32-bit mode with a 64-bit off_t type.
+AC_CACHE_CHECK([whether std::tr1::hash<off_t> is defined],
+[gold_cv_hash_off_t],
+[CXXFLAGS_hold=$CXXFLAGS
+CXXFLAGS="$CXXFLAGS $LFS_CFLAGS"
+AC_COMPILE_IFELSE([
+#include <sys/types.h>
+#include <tr1/unordered_map>
+std::tr1::hash<off_t> h;
+],
+[gold_cv_hash_off_t=yes],
+[gold_cv_hash_off_t=no])
+CXXFLAGS=$CFLAGS_hold])
+if test "$gold_cv_hash_off_t" = "yes"; then
+ AC_DEFINE(HAVE_TR1_HASH_OFF_T, 1,
+ [Define if std::tr1::hash<off_t> is usable])
+fi
+
# gcc 4.3.0 doesn't recognize the printf attribute on a template
# function. Check for that. This is gcc bug 35546. This test can
# probably be removed after the bug has been fixed for a while.
@@ -490,8 +562,19 @@ if test "$gold_cv_stat_st_mtim" = "yes"; then
[Define if struct stat has a field st_mtim with timespec for mtime])
fi
+dnl Check if gcc supports the -gpubnames option.
+save_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS -gpubnames"
+AC_COMPILE_IFELSE([int i;], [have_pubnames=yes], [have_pubnames=no])
+CXXFLAGS="$save_CXXFLAGS"
+AM_CONDITIONAL(HAVE_PUBNAMES, test "$have_pubnames" = "yes")
+
AC_LANG_POP(C++)
+AC_CHECK_HEADERS(locale.h)
+AC_CHECK_FUNCS(setlocale)
+AM_LC_MESSAGES
+
AM_MAINTAINER_MODE
AC_OUTPUT(Makefile testsuite/Makefile po/Makefile.in:po/Make-in)
diff --git a/binutils-2.22/gold/copy-relocs.cc b/binutils-2.22/gold/copy-relocs.cc
index 20b110d..92c5aea 100644
--- a/binutils-2.22/gold/copy-relocs.cc
+++ b/binutils-2.22/gold/copy-relocs.cc
@@ -1,6 +1,6 @@
// copy-relocs.cc -- handle COPY relocations for gold.
-// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -41,10 +41,10 @@ Copy_relocs<sh_type, size, big_endian>::Copy_reloc_entry::emit(
// emitted a COPY relocation, and we do not want to emit this
// dynamic relocation.
if (this->sym_->is_from_dynobj())
- reloc_section->add_global(this->sym_, this->reloc_type_,
- this->output_section_, this->relobj_,
- this->shndx_, this->address_,
- this->addend_);
+ reloc_section->add_global_generic(this->sym_, this->reloc_type_,
+ this->output_section_, this->relobj_,
+ this->shndx_, this->address_,
+ this->addend_);
}
// Copy_relocs methods.
@@ -115,7 +115,8 @@ Copy_relocs<sh_type, size, big_endian>::emit_copy_reloc(
symtab->define_with_copy_reloc(sym, posd, offset);
// Add the COPY relocation to the dynamic reloc section.
- reloc_section->add_global(sym, this->copy_reloc_type_, posd, offset, 0);
+ reloc_section->add_global_generic(sym, this->copy_reloc_type_, posd,
+ offset, 0);
}
// Make a COPY relocation for SYM and emit it.
diff --git a/binutils-2.22/gold/descriptors.cc b/binutils-2.22/gold/descriptors.cc
index 63b4cf9..2ab0d5c 100644
--- a/binutils-2.22/gold/descriptors.cc
+++ b/binutils-2.22/gold/descriptors.cc
@@ -50,8 +50,6 @@ set_close_on_exec(int fd)
// Mingw does not define F_SETFD.
#ifdef F_SETFD
fcntl(fd, F_SETFD, FD_CLOEXEC);
-#else
- (void)fd;
#endif
}
diff --git a/binutils-2.22/gold/dirsearch.cc b/binutils-2.22/gold/dirsearch.cc
index 1ae2055..a6114a4 100644
--- a/binutils-2.22/gold/dirsearch.cc
+++ b/binutils-2.22/gold/dirsearch.cc
@@ -25,6 +25,7 @@
#include <cerrno>
#include <cstring>
#include <sys/types.h>
+#include <sys/stat.h>
#include <dirent.h>
#include "debug.h"
@@ -277,4 +278,28 @@ Dirsearch::find(const std::vector<std::string>& names,
return std::string();
}
+// Search for a file in a directory list. This is a low-level function and
+// therefore can be used before options and parameters are set.
+
+std::string
+Dirsearch::find_file_in_dir_list(const std::string& name,
+ const General_options::Dir_list& directories,
+ const std::string& extra_search_dir)
+{
+ struct stat buf;
+ std::string extra_name = extra_search_dir + '/' + name;
+
+ if (stat(extra_name.c_str(), &buf) == 0)
+ return extra_name;
+ for (General_options::Dir_list::const_iterator dir = directories.begin();
+ dir != directories.end();
+ ++dir)
+ {
+ std::string full_name = dir->name() + '/' + name;
+ if (stat(full_name.c_str(), &buf) == 0)
+ return full_name;
+ }
+ return name;
+}
+
} // End namespace gold.
diff --git a/binutils-2.22/gold/dirsearch.h b/binutils-2.22/gold/dirsearch.h
index 270cef6..ebc0b5b 100644
--- a/binutils-2.22/gold/dirsearch.h
+++ b/binutils-2.22/gold/dirsearch.h
@@ -67,6 +67,13 @@ class Dirsearch
token()
{ return &this->token_; }
+ // Search for a file in a directory list. This is a low-level function and
+ // therefore can be used before options and parameters are set.
+ static std::string
+ find_file_in_dir_list(const std::string& name,
+ const General_options::Dir_list& directories,
+ const std::string& extra_search_dir);
+
private:
// We can not copy this class.
Dirsearch(const Dirsearch&);
diff --git a/binutils-2.22/gold/dwarf_reader.cc b/binutils-2.22/gold/dwarf_reader.cc
index e1c3c97..ac87f4b 100644
--- a/binutils-2.22/gold/dwarf_reader.cc
+++ b/binutils-2.22/gold/dwarf_reader.cc
@@ -1,6 +1,6 @@
// dwarf_reader.cc -- parse dwarf2/3 debug information
-// Copyright 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -36,6 +36,1370 @@
namespace gold {
+// Class Sized_elf_reloc_mapper
+
+// Initialize the relocation tracker for section RELOC_SHNDX.
+
+template<int size, bool big_endian>
+bool
+Sized_elf_reloc_mapper<size, big_endian>::do_initialize(
+ unsigned int reloc_shndx, unsigned int reloc_type)
+{
+ this->reloc_type_ = reloc_type;
+ return this->track_relocs_.initialize(this->object_, reloc_shndx,
+ reloc_type);
+}
+
+// Looks in the symtab to see what section a symbol is in.
+
+template<int size, bool big_endian>
+unsigned int
+Sized_elf_reloc_mapper<size, big_endian>::symbol_section(
+ unsigned int symndx, Address* value, bool* is_ordinary)
+{
+ const int symsize = elfcpp::Elf_sizes<size>::sym_size;
+ gold_assert((symndx + 1) * symsize <= this->symtab_size_);
+ elfcpp::Sym<size, big_endian> elfsym(this->symtab_ + symndx * symsize);
+ *value = elfsym.get_st_value();
+ return this->object_->adjust_sym_shndx(symndx, elfsym.get_st_shndx(),
+ is_ordinary);
+}
+
+// Return the section index and offset within the section of
+// the target of the relocation for RELOC_OFFSET.
+
+template<int size, bool big_endian>
+unsigned int
+Sized_elf_reloc_mapper<size, big_endian>::do_get_reloc_target(
+ off_t reloc_offset, off_t* target_offset)
+{
+ this->track_relocs_.advance(reloc_offset);
+ if (reloc_offset != this->track_relocs_.next_offset())
+ return 0;
+ unsigned int symndx = this->track_relocs_.next_symndx();
+ typename elfcpp::Elf_types<size>::Elf_Addr value;
+ bool is_ordinary;
+ unsigned int target_shndx = this->symbol_section(symndx, &value,
+ &is_ordinary);
+ if (!is_ordinary)
+ return 0;
+ if (this->reloc_type_ == elfcpp::SHT_RELA)
+ value += this->track_relocs_.next_addend();
+ *target_offset = value;
+ return target_shndx;
+}
+
+static inline Elf_reloc_mapper*
+make_elf_reloc_mapper(Object* object, const unsigned char* symtab,
+ off_t symtab_size)
+{
+ switch (parameters->size_and_endianness())
+ {
+#ifdef HAVE_TARGET_32_LITTLE
+ case Parameters::TARGET_32_LITTLE:
+ return new Sized_elf_reloc_mapper<32, false>(object, symtab,
+ symtab_size);
+#endif
+#ifdef HAVE_TARGET_32_BIG
+ case Parameters::TARGET_32_BIG:
+ return new Sized_elf_reloc_mapper<32, true>(object, symtab,
+ symtab_size);
+#endif
+#ifdef HAVE_TARGET_64_LITTLE
+ case Parameters::TARGET_64_LITTLE:
+ return new Sized_elf_reloc_mapper<64, false>(object, symtab,
+ symtab_size);
+#endif
+#ifdef HAVE_TARGET_64_BIG
+ case Parameters::TARGET_64_BIG:
+ return new Sized_elf_reloc_mapper<64, true>(object, symtab,
+ symtab_size);
+#endif
+ default:
+ gold_unreachable();
+ }
+}
+
+// class Dwarf_abbrev_table
+
+void
+Dwarf_abbrev_table::clear_abbrev_codes()
+{
+ for (unsigned int code = 0; code < this->low_abbrev_code_max_; ++code)
+ {
+ if (this->low_abbrev_codes_[code] != NULL)
+ {
+ delete this->low_abbrev_codes_[code];
+ this->low_abbrev_codes_[code] = NULL;
+ }
+ }
+ for (Abbrev_code_table::iterator it = this->high_abbrev_codes_.begin();
+ it != this->high_abbrev_codes_.end();
+ ++it)
+ {
+ if (it->second != NULL)
+ delete it->second;
+ }
+ this->high_abbrev_codes_.clear();
+}
+
+// Read the abbrev table from an object file.
+
+bool
+Dwarf_abbrev_table::do_read_abbrevs(
+ Relobj* object,
+ unsigned int abbrev_shndx,
+ off_t abbrev_offset)
+{
+ this->clear_abbrev_codes();
+
+ // If we don't have relocations, abbrev_shndx will be 0, and
+ // we'll have to hunt for the .debug_abbrev section.
+ if (abbrev_shndx == 0 && this->abbrev_shndx_ > 0)
+ abbrev_shndx = this->abbrev_shndx_;
+ else if (abbrev_shndx == 0)
+ {
+ for (unsigned int i = 1; i < object->shnum(); ++i)
+ {
+ std::string name = object->section_name(i);
+ if (name == ".debug_abbrev")
+ {
+ abbrev_shndx = i;
+ // Correct the offset. For incremental update links, we have a
+ // relocated offset that is relative to the output section, but
+ // here we need an offset relative to the input section.
+ abbrev_offset -= object->output_section_offset(i);
+ break;
+ }
+ }
+ if (abbrev_shndx == 0)
+ return false;
+ }
+
+ // Get the section contents and decompress if necessary.
+ if (abbrev_shndx != this->abbrev_shndx_)
+ {
+ if (this->owns_buffer_ && this->buffer_ != NULL)
+ {
+ delete[] this->buffer_;
+ this->owns_buffer_ = false;
+ }
+
+ section_size_type buffer_size;
+ this->buffer_ =
+ object->decompressed_section_contents(abbrev_shndx,
+ &buffer_size,
+ &this->owns_buffer_);
+ this->buffer_end_ = this->buffer_ + buffer_size;
+ this->abbrev_shndx_ = abbrev_shndx;
+ }
+
+ this->buffer_pos_ = this->buffer_ + abbrev_offset;
+ return true;
+}
+
+// Lookup the abbrev code entry for CODE. This function is called
+// only when the abbrev code is not in the direct lookup table.
+// It may be in the hash table, it may not have been read yet,
+// or it may not exist in the abbrev table.
+
+const Dwarf_abbrev_table::Abbrev_code*
+Dwarf_abbrev_table::do_get_abbrev(unsigned int code)
+{
+ // See if the abbrev code is already in the hash table.
+ Abbrev_code_table::const_iterator it = this->high_abbrev_codes_.find(code);
+ if (it != this->high_abbrev_codes_.end())
+ return it->second;
+
+ // Read and store abbrev code definitions until we find the
+ // one we're looking for.
+ for (;;)
+ {
+ // Read the abbrev code. A zero here indicates the end of the
+ // abbrev table.
+ size_t len;
+ if (this->buffer_pos_ >= this->buffer_end_)
+ return NULL;
+ uint64_t nextcode = read_unsigned_LEB_128(this->buffer_pos_, &len);
+ if (nextcode == 0)
+ {
+ this->buffer_pos_ = this->buffer_end_;
+ return NULL;
+ }
+ this->buffer_pos_ += len;
+
+ // Read the tag.
+ if (this->buffer_pos_ >= this->buffer_end_)
+ return NULL;
+ uint64_t tag = read_unsigned_LEB_128(this->buffer_pos_, &len);
+ this->buffer_pos_ += len;
+
+ // Read the has_children flag.
+ if (this->buffer_pos_ >= this->buffer_end_)
+ return NULL;
+ bool has_children = *this->buffer_pos_ == elfcpp::DW_CHILDREN_yes;
+ this->buffer_pos_ += 1;
+
+ // Read the list of (attribute, form) pairs.
+ Abbrev_code* entry = new Abbrev_code(tag, has_children);
+ for (;;)
+ {
+ // Read the attribute.
+ if (this->buffer_pos_ >= this->buffer_end_)
+ return NULL;
+ uint64_t attr = read_unsigned_LEB_128(this->buffer_pos_, &len);
+ this->buffer_pos_ += len;
+
+ // Read the form.
+ if (this->buffer_pos_ >= this->buffer_end_)
+ return NULL;
+ uint64_t form = read_unsigned_LEB_128(this->buffer_pos_, &len);
+ this->buffer_pos_ += len;
+
+ // A (0,0) pair terminates the list.
+ if (attr == 0 && form == 0)
+ break;
+
+ if (attr == elfcpp::DW_AT_sibling)
+ entry->has_sibling_attribute = true;
+
+ entry->add_attribute(attr, form);
+ }
+
+ this->store_abbrev(nextcode, entry);
+ if (nextcode == code)
+ return entry;
+ }
+
+ return NULL;
+}
+
+// class Dwarf_ranges_table
+
+// Read the ranges table from an object file.
+
+bool
+Dwarf_ranges_table::read_ranges_table(
+ Relobj* object,
+ const unsigned char* symtab,
+ off_t symtab_size,
+ unsigned int ranges_shndx)
+{
+ // If we've already read this abbrev table, return immediately.
+ if (this->ranges_shndx_ > 0
+ && this->ranges_shndx_ == ranges_shndx)
+ return true;
+
+ // If we don't have relocations, ranges_shndx will be 0, and
+ // we'll have to hunt for the .debug_ranges section.
+ if (ranges_shndx == 0 && this->ranges_shndx_ > 0)
+ ranges_shndx = this->ranges_shndx_;
+ else if (ranges_shndx == 0)
+ {
+ for (unsigned int i = 1; i < object->shnum(); ++i)
+ {
+ std::string name = object->section_name(i);
+ if (name == ".debug_ranges")
+ {
+ ranges_shndx = i;
+ this->output_section_offset_ = object->output_section_offset(i);
+ break;
+ }
+ }
+ if (ranges_shndx == 0)
+ return false;
+ }
+
+ // Get the section contents and decompress if necessary.
+ if (ranges_shndx != this->ranges_shndx_)
+ {
+ if (this->owns_ranges_buffer_ && this->ranges_buffer_ != NULL)
+ {
+ delete[] this->ranges_buffer_;
+ this->owns_ranges_buffer_ = false;
+ }
+
+ section_size_type buffer_size;
+ this->ranges_buffer_ =
+ object->decompressed_section_contents(ranges_shndx,
+ &buffer_size,
+ &this->owns_ranges_buffer_);
+ this->ranges_buffer_end_ = this->ranges_buffer_ + buffer_size;
+ this->ranges_shndx_ = ranges_shndx;
+ }
+
+ if (this->ranges_reloc_mapper_ != NULL)
+ {
+ delete this->ranges_reloc_mapper_;
+ this->ranges_reloc_mapper_ = NULL;
+ }
+
+ // For incremental objects, we have no relocations.
+ if (object->is_incremental())
+ return true;
+
+ // Find the relocation section for ".debug_ranges".
+ unsigned int reloc_shndx = 0;
+ unsigned int reloc_type = 0;
+ for (unsigned int i = 0; i < object->shnum(); ++i)
+ {
+ reloc_type = object->section_type(i);
+ if ((reloc_type == elfcpp::SHT_REL
+ || reloc_type == elfcpp::SHT_RELA)
+ && object->section_info(i) == ranges_shndx)
+ {
+ reloc_shndx = i;
+ break;
+ }
+ }
+
+ this->ranges_reloc_mapper_ = make_elf_reloc_mapper(object, symtab,
+ symtab_size);
+ this->ranges_reloc_mapper_->initialize(reloc_shndx, reloc_type);
+
+ return true;
+}
+
+// Read a range list from section RANGES_SHNDX at offset RANGES_OFFSET.
+
+Dwarf_range_list*
+Dwarf_ranges_table::read_range_list(
+ Relobj* object,
+ const unsigned char* symtab,
+ off_t symtab_size,
+ unsigned int addr_size,
+ unsigned int ranges_shndx,
+ off_t offset)
+{
+ Dwarf_range_list* ranges;
+
+ if (!this->read_ranges_table(object, symtab, symtab_size, ranges_shndx))
+ return NULL;
+
+ // Correct the offset. For incremental update links, we have a
+ // relocated offset that is relative to the output section, but
+ // here we need an offset relative to the input section.
+ offset -= this->output_section_offset_;
+
+ // Read the range list at OFFSET.
+ ranges = new Dwarf_range_list();
+ off_t base = 0;
+ for (;
+ this->ranges_buffer_ + offset < this->ranges_buffer_end_;
+ offset += 2 * addr_size)
+ {
+ off_t start;
+ off_t end;
+
+ // Read the raw contents of the section.
+ if (addr_size == 4)
+ {
+ start = read_from_pointer<32>(this->ranges_buffer_ + offset);
+ end = read_from_pointer<32>(this->ranges_buffer_ + offset + 4);
+ }
+ else
+ {
+ start = read_from_pointer<64>(this->ranges_buffer_ + offset);
+ end = read_from_pointer<64>(this->ranges_buffer_ + offset + 8);
+ }
+
+ // Check for relocations and adjust the values.
+ unsigned int shndx1 = 0;
+ unsigned int shndx2 = 0;
+ if (this->ranges_reloc_mapper_ != NULL)
+ {
+ shndx1 =
+ this->ranges_reloc_mapper_->get_reloc_target(offset, &start);
+ shndx2 =
+ this->ranges_reloc_mapper_->get_reloc_target(offset + addr_size,
+ &end);
+ }
+
+ // End of list is marked by a pair of zeroes.
+ if (shndx1 == 0 && start == 0 && end == 0)
+ break;
+
+ // A "base address selection entry" is identified by
+ // 0xffffffff for the first value of the pair. The second
+ // value is used as a base for subsequent range list entries.
+ if (shndx1 == 0 && start == -1)
+ base = end;
+ else if (shndx1 == shndx2)
+ {
+ if (shndx1 == 0 || object->is_section_included(shndx1))
+ ranges->add(shndx1, base + start, base + end);
+ }
+ else
+ gold_warning(_("%s: DWARF info may be corrupt; offsets in a "
+ "range list entry are in different sections"),
+ object->name().c_str());
+ }
+
+ return ranges;
+}
+
+// class Dwarf_pubnames_table
+
+// Read the pubnames section SHNDX from the object file.
+
+bool
+Dwarf_pubnames_table::read_section(Relobj* object, unsigned int shndx)
+{
+ section_size_type buffer_size;
+
+ // If we don't have relocations, shndx will be 0, and
+ // we'll have to hunt for the .debug_pubnames/pubtypes section.
+ if (shndx == 0)
+ {
+ const char* name = (this->is_pubtypes_
+ ? ".debug_pubtypes"
+ : ".debug_pubnames");
+ for (unsigned int i = 1; i < object->shnum(); ++i)
+ {
+ if (object->section_name(i) == name)
+ {
+ shndx = i;
+ this->output_section_offset_ = object->output_section_offset(i);
+ break;
+ }
+ }
+ if (shndx == 0)
+ return false;
+ }
+
+ this->buffer_ = object->decompressed_section_contents(shndx,
+ &buffer_size,
+ &this->owns_buffer_);
+ if (this->buffer_ == NULL)
+ return false;
+ this->buffer_end_ = this->buffer_ + buffer_size;
+ return true;
+}
+
+// Read the header for the set at OFFSET.
+
+bool
+Dwarf_pubnames_table::read_header(off_t offset)
+{
+ // Correct the offset. For incremental update links, we have a
+ // relocated offset that is relative to the output section, but
+ // here we need an offset relative to the input section.
+ offset -= this->output_section_offset_;
+
+ if (offset < 0 || offset + 14 >= this->buffer_end_ - this->buffer_)
+ return false;
+
+ const unsigned char* pinfo = this->buffer_ + offset;
+
+ // Read the unit_length field.
+ uint32_t unit_length = read_from_pointer<32>(pinfo);
+ pinfo += 4;
+ if (unit_length == 0xffffffff)
+ {
+ unit_length = read_from_pointer<64>(pinfo);
+ pinfo += 8;
+ this->offset_size_ = 8;
+ }
+ else
+ this->offset_size_ = 4;
+
+ // Check the version.
+ unsigned int version = read_from_pointer<16>(pinfo);
+ pinfo += 2;
+ if (version != 2)
+ return false;
+
+ // Skip the debug_info_offset and debug_info_size fields.
+ pinfo += 2 * this->offset_size_;
+
+ if (pinfo >= this->buffer_end_)
+ return false;
+
+ this->pinfo_ = pinfo;
+ return true;
+}
+
+// Read the next name from the set.
+
+const char*
+Dwarf_pubnames_table::next_name()
+{
+ const unsigned char* pinfo = this->pinfo_;
+
+ // Read the offset within the CU. If this is zero, we have reached
+ // the end of the list.
+ uint32_t offset;
+ if (this->offset_size_ == 4)
+ offset = read_from_pointer<32>(&pinfo);
+ else
+ offset = read_from_pointer<64>(&pinfo);
+ if (offset == 0)
+ return NULL;
+
+ // Return a pointer to the string at the current location,
+ // and advance the pointer to the next entry.
+ const char* ret = reinterpret_cast<const char*>(pinfo);
+ while (pinfo < this->buffer_end_ && *pinfo != '\0')
+ ++pinfo;
+ if (pinfo < this->buffer_end_)
+ ++pinfo;
+
+ this->pinfo_ = pinfo;
+ return ret;
+}
+
+// class Dwarf_die
+
+Dwarf_die::Dwarf_die(
+ Dwarf_info_reader* dwinfo,
+ off_t die_offset,
+ Dwarf_die* parent)
+ : dwinfo_(dwinfo), parent_(parent), die_offset_(die_offset),
+ child_offset_(0), sibling_offset_(0), abbrev_code_(NULL), attributes_(),
+ attributes_read_(false), name_(NULL), name_off_(-1), linkage_name_(NULL),
+ linkage_name_off_(-1), string_shndx_(0), specification_(0),
+ abstract_origin_(0)
+{
+ size_t len;
+ const unsigned char* pdie = dwinfo->buffer_at_offset(die_offset);
+ if (pdie == NULL)
+ return;
+ unsigned int code = read_unsigned_LEB_128(pdie, &len);
+ if (code == 0)
+ {
+ if (parent != NULL)
+ parent->set_sibling_offset(die_offset + len);
+ return;
+ }
+ this->attr_offset_ = len;
+
+ // Lookup the abbrev code in the abbrev table.
+ this->abbrev_code_ = dwinfo->get_abbrev(code);
+}
+
+// Read all the attributes of the DIE.
+
+bool
+Dwarf_die::read_attributes()
+{
+ if (this->attributes_read_)
+ return true;
+
+ gold_assert(this->abbrev_code_ != NULL);
+
+ const unsigned char* pdie =
+ this->dwinfo_->buffer_at_offset(this->die_offset_);
+ if (pdie == NULL)
+ return false;
+ const unsigned char* pattr = pdie + this->attr_offset_;
+
+ unsigned int nattr = this->abbrev_code_->attributes.size();
+ this->attributes_.reserve(nattr);
+ for (unsigned int i = 0; i < nattr; ++i)
+ {
+ size_t len;
+ unsigned int attr = this->abbrev_code_->attributes[i].attr;
+ unsigned int form = this->abbrev_code_->attributes[i].form;
+ if (form == elfcpp::DW_FORM_indirect)
+ {
+ form = read_unsigned_LEB_128(pattr, &len);
+ pattr += len;
+ }
+ off_t attr_off = this->die_offset_ + (pattr - pdie);
+ bool ref_form = false;
+ Attribute_value attr_value;
+ attr_value.attr = attr;
+ attr_value.form = form;
+ attr_value.aux.shndx = 0;
+ switch(form)
+ {
+ case elfcpp::DW_FORM_flag_present:
+ attr_value.val.intval = 1;
+ break;
+ case elfcpp::DW_FORM_strp:
+ {
+ off_t str_off;
+ if (this->dwinfo_->offset_size() == 4)
+ str_off = read_from_pointer<32>(&pattr);
+ else
+ str_off = read_from_pointer<64>(&pattr);
+ unsigned int shndx =
+ this->dwinfo_->lookup_reloc(attr_off, &str_off);
+ attr_value.aux.shndx = shndx;
+ attr_value.val.refval = str_off;
+ break;
+ }
+ case elfcpp::DW_FORM_sec_offset:
+ {
+ off_t sec_off;
+ if (this->dwinfo_->offset_size() == 4)
+ sec_off = read_from_pointer<32>(&pattr);
+ else
+ sec_off = read_from_pointer<64>(&pattr);
+ unsigned int shndx =
+ this->dwinfo_->lookup_reloc(attr_off, &sec_off);
+ attr_value.aux.shndx = shndx;
+ attr_value.val.refval = sec_off;
+ ref_form = true;
+ break;
+ }
+ case elfcpp::DW_FORM_addr:
+ case elfcpp::DW_FORM_ref_addr:
+ {
+ off_t sec_off;
+ if (this->dwinfo_->address_size() == 4)
+ sec_off = read_from_pointer<32>(&pattr);
+ else
+ sec_off = read_from_pointer<64>(&pattr);
+ unsigned int shndx =
+ this->dwinfo_->lookup_reloc(attr_off, &sec_off);
+ attr_value.aux.shndx = shndx;
+ attr_value.val.refval = sec_off;
+ ref_form = true;
+ break;
+ }
+ case elfcpp::DW_FORM_block1:
+ attr_value.aux.blocklen = *pattr++;
+ attr_value.val.blockval = pattr;
+ pattr += attr_value.aux.blocklen;
+ break;
+ case elfcpp::DW_FORM_block2:
+ attr_value.aux.blocklen = read_from_pointer<16>(&pattr);
+ attr_value.val.blockval = pattr;
+ pattr += attr_value.aux.blocklen;
+ break;
+ case elfcpp::DW_FORM_block4:
+ attr_value.aux.blocklen = read_from_pointer<32>(&pattr);
+ attr_value.val.blockval = pattr;
+ pattr += attr_value.aux.blocklen;
+ break;
+ case elfcpp::DW_FORM_block:
+ case elfcpp::DW_FORM_exprloc:
+ attr_value.aux.blocklen = read_unsigned_LEB_128(pattr, &len);
+ attr_value.val.blockval = pattr + len;
+ pattr += len + attr_value.aux.blocklen;
+ break;
+ case elfcpp::DW_FORM_data1:
+ case elfcpp::DW_FORM_flag:
+ attr_value.val.intval = *pattr++;
+ break;
+ case elfcpp::DW_FORM_ref1:
+ attr_value.val.refval = *pattr++;
+ ref_form = true;
+ break;
+ case elfcpp::DW_FORM_data2:
+ attr_value.val.intval = read_from_pointer<16>(&pattr);
+ break;
+ case elfcpp::DW_FORM_ref2:
+ attr_value.val.refval = read_from_pointer<16>(&pattr);
+ ref_form = true;
+ break;
+ case elfcpp::DW_FORM_data4:
+ {
+ off_t sec_off;
+ sec_off = read_from_pointer<32>(&pattr);
+ unsigned int shndx =
+ this->dwinfo_->lookup_reloc(attr_off, &sec_off);
+ attr_value.aux.shndx = shndx;
+ attr_value.val.intval = sec_off;
+ break;
+ }
+ case elfcpp::DW_FORM_ref4:
+ {
+ off_t sec_off;
+ sec_off = read_from_pointer<32>(&pattr);
+ unsigned int shndx =
+ this->dwinfo_->lookup_reloc(attr_off, &sec_off);
+ attr_value.aux.shndx = shndx;
+ attr_value.val.refval = sec_off;
+ ref_form = true;
+ break;
+ }
+ case elfcpp::DW_FORM_data8:
+ {
+ off_t sec_off;
+ sec_off = read_from_pointer<64>(&pattr);
+ unsigned int shndx =
+ this->dwinfo_->lookup_reloc(attr_off, &sec_off);
+ attr_value.aux.shndx = shndx;
+ attr_value.val.intval = sec_off;
+ break;
+ }
+ case elfcpp::DW_FORM_ref_sig8:
+ attr_value.val.uintval = read_from_pointer<64>(&pattr);
+ break;
+ case elfcpp::DW_FORM_ref8:
+ {
+ off_t sec_off;
+ sec_off = read_from_pointer<64>(&pattr);
+ unsigned int shndx =
+ this->dwinfo_->lookup_reloc(attr_off, &sec_off);
+ attr_value.aux.shndx = shndx;
+ attr_value.val.refval = sec_off;
+ ref_form = true;
+ break;
+ }
+ case elfcpp::DW_FORM_ref_udata:
+ attr_value.val.refval = read_unsigned_LEB_128(pattr, &len);
+ ref_form = true;
+ pattr += len;
+ break;
+ case elfcpp::DW_FORM_udata:
+ attr_value.val.uintval = read_unsigned_LEB_128(pattr, &len);
+ pattr += len;
+ break;
+ case elfcpp::DW_FORM_sdata:
+ attr_value.val.intval = read_signed_LEB_128(pattr, &len);
+ pattr += len;
+ break;
+ case elfcpp::DW_FORM_string:
+ attr_value.val.stringval = reinterpret_cast<const char*>(pattr);
+ len = strlen(attr_value.val.stringval);
+ pattr += len + 1;
+ break;
+ default:
+ return false;
+ }
+
+ // Cache the most frequently-requested attributes.
+ switch (attr)
+ {
+ case elfcpp::DW_AT_name:
+ if (form == elfcpp::DW_FORM_string)
+ this->name_ = attr_value.val.stringval;
+ else if (form == elfcpp::DW_FORM_strp)
+ {
+ // All indirect strings should refer to the same
+ // string section, so we just save the last one seen.
+ this->string_shndx_ = attr_value.aux.shndx;
+ this->name_off_ = attr_value.val.refval;
+ }
+ break;
+ case elfcpp::DW_AT_linkage_name:
+ case elfcpp::DW_AT_MIPS_linkage_name:
+ if (form == elfcpp::DW_FORM_string)
+ this->linkage_name_ = attr_value.val.stringval;
+ else if (form == elfcpp::DW_FORM_strp)
+ {
+ // All indirect strings should refer to the same
+ // string section, so we just save the last one seen.
+ this->string_shndx_ = attr_value.aux.shndx;
+ this->linkage_name_off_ = attr_value.val.refval;
+ }
+ break;
+ case elfcpp::DW_AT_specification:
+ if (ref_form)
+ this->specification_ = attr_value.val.refval;
+ break;
+ case elfcpp::DW_AT_abstract_origin:
+ if (ref_form)
+ this->abstract_origin_ = attr_value.val.refval;
+ break;
+ case elfcpp::DW_AT_sibling:
+ if (ref_form && attr_value.aux.shndx == 0)
+ this->sibling_offset_ = attr_value.val.refval;
+ default:
+ break;
+ }
+
+ this->attributes_.push_back(attr_value);
+ }
+
+ // Now that we know where the next DIE begins, record the offset
+ // to avoid later recalculation.
+ if (this->has_children())
+ this->child_offset_ = this->die_offset_ + (pattr - pdie);
+ else
+ this->sibling_offset_ = this->die_offset_ + (pattr - pdie);
+
+ this->attributes_read_ = true;
+ return true;
+}
+
+// Skip all the attributes of the DIE and return the offset of the next DIE.
+
+off_t
+Dwarf_die::skip_attributes()
+{
+ gold_assert(this->abbrev_code_ != NULL);
+
+ const unsigned char* pdie =
+ this->dwinfo_->buffer_at_offset(this->die_offset_);
+ if (pdie == NULL)
+ return 0;
+ const unsigned char* pattr = pdie + this->attr_offset_;
+
+ for (unsigned int i = 0; i < this->abbrev_code_->attributes.size(); ++i)
+ {
+ size_t len;
+ unsigned int form = this->abbrev_code_->attributes[i].form;
+ if (form == elfcpp::DW_FORM_indirect)
+ {
+ form = read_unsigned_LEB_128(pattr, &len);
+ pattr += len;
+ }
+ switch(form)
+ {
+ case elfcpp::DW_FORM_flag_present:
+ break;
+ case elfcpp::DW_FORM_strp:
+ case elfcpp::DW_FORM_sec_offset:
+ pattr += this->dwinfo_->offset_size();
+ break;
+ case elfcpp::DW_FORM_addr:
+ case elfcpp::DW_FORM_ref_addr:
+ pattr += this->dwinfo_->address_size();
+ break;
+ case elfcpp::DW_FORM_block1:
+ pattr += 1 + *pattr;
+ break;
+ case elfcpp::DW_FORM_block2:
+ {
+ uint16_t block_size;
+ block_size = read_from_pointer<16>(&pattr);
+ pattr += block_size;
+ break;
+ }
+ case elfcpp::DW_FORM_block4:
+ {
+ uint32_t block_size;
+ block_size = read_from_pointer<32>(&pattr);
+ pattr += block_size;
+ break;
+ }
+ case elfcpp::DW_FORM_block:
+ case elfcpp::DW_FORM_exprloc:
+ {
+ uint64_t block_size;
+ block_size = read_unsigned_LEB_128(pattr, &len);
+ pattr += len + block_size;
+ break;
+ }
+ case elfcpp::DW_FORM_data1:
+ case elfcpp::DW_FORM_ref1:
+ case elfcpp::DW_FORM_flag:
+ pattr += 1;
+ break;
+ case elfcpp::DW_FORM_data2:
+ case elfcpp::DW_FORM_ref2:
+ pattr += 2;
+ break;
+ case elfcpp::DW_FORM_data4:
+ case elfcpp::DW_FORM_ref4:
+ pattr += 4;
+ break;
+ case elfcpp::DW_FORM_data8:
+ case elfcpp::DW_FORM_ref8:
+ case elfcpp::DW_FORM_ref_sig8:
+ pattr += 8;
+ break;
+ case elfcpp::DW_FORM_ref_udata:
+ case elfcpp::DW_FORM_udata:
+ read_unsigned_LEB_128(pattr, &len);
+ pattr += len;
+ break;
+ case elfcpp::DW_FORM_sdata:
+ read_signed_LEB_128(pattr, &len);
+ pattr += len;
+ break;
+ case elfcpp::DW_FORM_string:
+ len = strlen(reinterpret_cast<const char*>(pattr));
+ pattr += len + 1;
+ break;
+ default:
+ return 0;
+ }
+ }
+
+ return this->die_offset_ + (pattr - pdie);
+}
+
+// Get the name of the DIE and cache it.
+
+void
+Dwarf_die::set_name()
+{
+ if (this->name_ != NULL || !this->read_attributes())
+ return;
+ if (this->name_off_ != -1)
+ this->name_ = this->dwinfo_->get_string(this->name_off_,
+ this->string_shndx_);
+}
+
+// Get the linkage name of the DIE and cache it.
+
+void
+Dwarf_die::set_linkage_name()
+{
+ if (this->linkage_name_ != NULL || !this->read_attributes())
+ return;
+ if (this->linkage_name_off_ != -1)
+ this->linkage_name_ = this->dwinfo_->get_string(this->linkage_name_off_,
+ this->string_shndx_);
+}
+
+// Return the value of attribute ATTR.
+
+const Dwarf_die::Attribute_value*
+Dwarf_die::attribute(unsigned int attr)
+{
+ if (!this->read_attributes())
+ return NULL;
+ for (unsigned int i = 0; i < this->attributes_.size(); ++i)
+ {
+ if (this->attributes_[i].attr == attr)
+ return &this->attributes_[i];
+ }
+ return NULL;
+}
+
+const char*
+Dwarf_die::string_attribute(unsigned int attr)
+{
+ const Attribute_value* attr_val = this->attribute(attr);
+ if (attr_val == NULL)
+ return NULL;
+ switch (attr_val->form)
+ {
+ case elfcpp::DW_FORM_string:
+ return attr_val->val.stringval;
+ case elfcpp::DW_FORM_strp:
+ return this->dwinfo_->get_string(attr_val->val.refval,
+ attr_val->aux.shndx);
+ default:
+ return NULL;
+ }
+}
+
+int64_t
+Dwarf_die::int_attribute(unsigned int attr)
+{
+ const Attribute_value* attr_val = this->attribute(attr);
+ if (attr_val == NULL)
+ return 0;
+ switch (attr_val->form)
+ {
+ case elfcpp::DW_FORM_flag_present:
+ case elfcpp::DW_FORM_data1:
+ case elfcpp::DW_FORM_flag:
+ case elfcpp::DW_FORM_data2:
+ case elfcpp::DW_FORM_data4:
+ case elfcpp::DW_FORM_data8:
+ case elfcpp::DW_FORM_sdata:
+ return attr_val->val.intval;
+ default:
+ return 0;
+ }
+}
+
+uint64_t
+Dwarf_die::uint_attribute(unsigned int attr)
+{
+ const Attribute_value* attr_val = this->attribute(attr);
+ if (attr_val == NULL)
+ return 0;
+ switch (attr_val->form)
+ {
+ case elfcpp::DW_FORM_flag_present:
+ case elfcpp::DW_FORM_data1:
+ case elfcpp::DW_FORM_flag:
+ case elfcpp::DW_FORM_data4:
+ case elfcpp::DW_FORM_data8:
+ case elfcpp::DW_FORM_ref_sig8:
+ case elfcpp::DW_FORM_udata:
+ return attr_val->val.uintval;
+ default:
+ return 0;
+ }
+}
+
+off_t
+Dwarf_die::ref_attribute(unsigned int attr, unsigned int* shndx)
+{
+ const Attribute_value* attr_val = this->attribute(attr);
+ if (attr_val == NULL)
+ return -1;
+ switch (attr_val->form)
+ {
+ case elfcpp::DW_FORM_sec_offset:
+ case elfcpp::DW_FORM_addr:
+ case elfcpp::DW_FORM_ref_addr:
+ case elfcpp::DW_FORM_ref1:
+ case elfcpp::DW_FORM_ref2:
+ case elfcpp::DW_FORM_ref4:
+ case elfcpp::DW_FORM_ref8:
+ case elfcpp::DW_FORM_ref_udata:
+ *shndx = attr_val->aux.shndx;
+ return attr_val->val.refval;
+ case elfcpp::DW_FORM_ref_sig8:
+ *shndx = attr_val->aux.shndx;
+ return attr_val->val.uintval;
+ case elfcpp::DW_FORM_data4:
+ case elfcpp::DW_FORM_data8:
+ *shndx = attr_val->aux.shndx;
+ return attr_val->val.intval;
+ default:
+ return -1;
+ }
+}
+
+off_t
+Dwarf_die::address_attribute(unsigned int attr, unsigned int* shndx)
+{
+ const Attribute_value* attr_val = this->attribute(attr);
+ if (attr_val == NULL || attr_val->form != elfcpp::DW_FORM_addr)
+ return -1;
+
+ *shndx = attr_val->aux.shndx;
+ return attr_val->val.refval;
+}
+
+// Return the offset of this DIE's first child.
+
+off_t
+Dwarf_die::child_offset()
+{
+ gold_assert(this->abbrev_code_ != NULL);
+ if (!this->has_children())
+ return 0;
+ if (this->child_offset_ == 0)
+ this->child_offset_ = this->skip_attributes();
+ return this->child_offset_;
+}
+
+// Return the offset of this DIE's next sibling.
+
+off_t
+Dwarf_die::sibling_offset()
+{
+ gold_assert(this->abbrev_code_ != NULL);
+
+ if (this->sibling_offset_ != 0)
+ return this->sibling_offset_;
+
+ if (!this->has_children())
+ {
+ this->sibling_offset_ = this->skip_attributes();
+ return this->sibling_offset_;
+ }
+
+ if (this->has_sibling_attribute())
+ {
+ if (!this->read_attributes())
+ return 0;
+ if (this->sibling_offset_ != 0)
+ return this->sibling_offset_;
+ }
+
+ // Skip over the children.
+ off_t child_offset = this->child_offset();
+ while (child_offset > 0)
+ {
+ Dwarf_die die(this->dwinfo_, child_offset, this);
+ // The Dwarf_die ctor will set this DIE's sibling offset
+ // when it reads a zero abbrev code.
+ if (die.tag() == 0)
+ break;
+ child_offset = die.sibling_offset();
+ }
+
+ // This should be set by now. If not, there was a problem reading
+ // the DWARF info, and we return 0.
+ return this->sibling_offset_;
+}
+
+// class Dwarf_info_reader
+
+// Check that the pointer P is within the current compilation unit.
+
+inline bool
+Dwarf_info_reader::check_buffer(const unsigned char* p) const
+{
+ if (p > this->buffer_ + this->cu_offset_ + this->cu_length_)
+ {
+ gold_warning(_("%s: corrupt debug info in %s"),
+ this->object_->name().c_str(),
+ this->object_->section_name(this->shndx_).c_str());
+ return false;
+ }
+ return true;
+}
+
+// Begin parsing the debug info. This calls visit_compilation_unit()
+// or visit_type_unit() for each compilation or type unit found in the
+// section, and visit_die() for each top-level DIE.
+
+void
+Dwarf_info_reader::parse()
+{
+ switch (parameters->size_and_endianness())
+ {
+#ifdef HAVE_TARGET_32_LITTLE
+ case Parameters::TARGET_32_LITTLE:
+ this->do_parse<false>();
+ break;
+#endif
+#ifdef HAVE_TARGET_32_BIG
+ case Parameters::TARGET_32_BIG:
+ this->do_parse<true>();
+ break;
+#endif
+#ifdef HAVE_TARGET_64_LITTLE
+ case Parameters::TARGET_64_LITTLE:
+ this->do_parse<false>();
+ break;
+#endif
+#ifdef HAVE_TARGET_64_BIG
+ case Parameters::TARGET_64_BIG:
+ this->do_parse<true>();
+ break;
+#endif
+ default:
+ gold_unreachable();
+ }
+}
+
+template<bool big_endian>
+void
+Dwarf_info_reader::do_parse()
+{
+ // Get the section contents and decompress if necessary.
+ section_size_type buffer_size;
+ bool buffer_is_new;
+ this->buffer_ = this->object_->decompressed_section_contents(this->shndx_,
+ &buffer_size,
+ &buffer_is_new);
+ if (this->buffer_ == NULL || buffer_size == 0)
+ return;
+ this->buffer_end_ = this->buffer_ + buffer_size;
+
+ // The offset of this input section in the output section.
+ off_t section_offset = this->object_->output_section_offset(this->shndx_);
+
+ // Start tracking relocations for this section.
+ this->reloc_mapper_ = make_elf_reloc_mapper(this->object_, this->symtab_,
+ this->symtab_size_);
+ this->reloc_mapper_->initialize(this->reloc_shndx_, this->reloc_type_);
+
+ // Loop over compilation units (or type units).
+ unsigned int abbrev_shndx = 0;
+ off_t abbrev_offset = 0;
+ const unsigned char* pinfo = this->buffer_;
+ while (pinfo < this->buffer_end_)
+ {
+ // Read the compilation (or type) unit header.
+ const unsigned char* cu_start = pinfo;
+ this->cu_offset_ = cu_start - this->buffer_;
+ this->cu_length_ = this->buffer_end_ - cu_start;
+
+ // Read unit_length (4 or 12 bytes).
+ if (!this->check_buffer(pinfo + 4))
+ break;
+ uint32_t unit_length =
+ elfcpp::Swap_unaligned<32, big_endian>::readval(pinfo);
+ pinfo += 4;
+ if (unit_length == 0xffffffff)
+ {
+ if (!this->check_buffer(pinfo + 8))
+ break;
+ unit_length = elfcpp::Swap_unaligned<64, big_endian>::readval(pinfo);
+ pinfo += 8;
+ this->offset_size_ = 8;
+ }
+ else
+ this->offset_size_ = 4;
+ if (!this->check_buffer(pinfo + unit_length))
+ break;
+ const unsigned char* cu_end = pinfo + unit_length;
+ this->cu_length_ = cu_end - cu_start;
+ if (!this->check_buffer(pinfo + 2 + this->offset_size_ + 1))
+ break;
+
+ // Read version (2 bytes).
+ this->cu_version_ =
+ elfcpp::Swap_unaligned<16, big_endian>::readval(pinfo);
+ pinfo += 2;
+
+ // Read debug_abbrev_offset (4 or 8 bytes).
+ if (this->offset_size_ == 4)
+ abbrev_offset = elfcpp::Swap_unaligned<32, big_endian>::readval(pinfo);
+ else
+ abbrev_offset = elfcpp::Swap_unaligned<64, big_endian>::readval(pinfo);
+ if (this->reloc_shndx_ > 0)
+ {
+ off_t reloc_offset = pinfo - this->buffer_;
+ off_t value;
+ abbrev_shndx =
+ this->reloc_mapper_->get_reloc_target(reloc_offset, &value);
+ if (abbrev_shndx == 0)
+ return;
+ if (this->reloc_type_ == elfcpp::SHT_REL)
+ abbrev_offset += value;
+ else
+ abbrev_offset = value;
+ }
+ pinfo += this->offset_size_;
+
+ // Read address_size (1 byte).
+ this->address_size_ = *pinfo++;
+
+ // For type units, read the two extra fields.
+ uint64_t signature = 0;
+ off_t type_offset = 0;
+ if (this->is_type_unit_)
+ {
+ if (!this->check_buffer(pinfo + 8 + this->offset_size_))
+ break;
+
+ // Read type_signature (8 bytes).
+ signature = elfcpp::Swap_unaligned<64, big_endian>::readval(pinfo);
+ pinfo += 8;
+
+ // Read type_offset (4 or 8 bytes).
+ if (this->offset_size_ == 4)
+ type_offset =
+ elfcpp::Swap_unaligned<32, big_endian>::readval(pinfo);
+ else
+ type_offset =
+ elfcpp::Swap_unaligned<64, big_endian>::readval(pinfo);
+ pinfo += this->offset_size_;
+ }
+
+ // Read the .debug_abbrev table.
+ this->abbrev_table_.read_abbrevs(this->object_, abbrev_shndx,
+ abbrev_offset);
+
+ // Visit the root DIE.
+ Dwarf_die root_die(this,
+ pinfo - (this->buffer_ + this->cu_offset_),
+ NULL);
+ if (root_die.tag() != 0)
+ {
+ // Visit the CU or TU.
+ if (this->is_type_unit_)
+ this->visit_type_unit(section_offset + this->cu_offset_,
+ type_offset, signature, &root_die);
+ else
+ this->visit_compilation_unit(section_offset + this->cu_offset_,
+ cu_end - cu_start, &root_die);
+ }
+
+ // Advance to the next CU.
+ pinfo = cu_end;
+ }
+
+ if (buffer_is_new)
+ {
+ delete[] this->buffer_;
+ this->buffer_ = NULL;
+ }
+}
+
+// Read the DWARF string table.
+
+bool
+Dwarf_info_reader::do_read_string_table(unsigned int string_shndx)
+{
+ Relobj* object = this->object_;
+
+ // If we don't have relocations, string_shndx will be 0, and
+ // we'll have to hunt for the .debug_str section.
+ if (string_shndx == 0)
+ {
+ for (unsigned int i = 1; i < this->object_->shnum(); ++i)
+ {
+ std::string name = object->section_name(i);
+ if (name == ".debug_str")
+ {
+ string_shndx = i;
+ this->string_output_section_offset_ =
+ object->output_section_offset(i);
+ break;
+ }
+ }
+ if (string_shndx == 0)
+ return false;
+ }
+
+ if (this->owns_string_buffer_ && this->string_buffer_ != NULL)
+ {
+ delete[] this->string_buffer_;
+ this->owns_string_buffer_ = false;
+ }
+
+ // Get the secton contents and decompress if necessary.
+ section_size_type buffer_size;
+ const unsigned char* buffer =
+ object->decompressed_section_contents(string_shndx,
+ &buffer_size,
+ &this->owns_string_buffer_);
+ this->string_buffer_ = reinterpret_cast<const char*>(buffer);
+ this->string_buffer_end_ = this->string_buffer_ + buffer_size;
+ this->string_shndx_ = string_shndx;
+ return true;
+}
+
+// Look for a relocation at offset ATTR_OFF in the dwarf info,
+// and return the section index and offset of the target.
+
+unsigned int
+Dwarf_info_reader::lookup_reloc(off_t attr_off, off_t* target_off)
+{
+ off_t value;
+ attr_off += this->cu_offset_;
+ unsigned int shndx = this->reloc_mapper_->get_reloc_target(attr_off, &value);
+ if (shndx == 0)
+ return 0;
+ if (this->reloc_type_ == elfcpp::SHT_REL)
+ *target_off += value;
+ else
+ *target_off = value;
+ return shndx;
+}
+
+// Return a string from the DWARF string table.
+
+const char*
+Dwarf_info_reader::get_string(off_t str_off, unsigned int string_shndx)
+{
+ if (!this->read_string_table(string_shndx))
+ return NULL;
+
+ // Correct the offset. For incremental update links, we have a
+ // relocated offset that is relative to the output section, but
+ // here we need an offset relative to the input section.
+ str_off -= this->string_output_section_offset_;
+
+ const char* p = this->string_buffer_ + str_off;
+
+ if (p < this->string_buffer_ || p >= this->string_buffer_end_)
+ return NULL;
+
+ return p;
+}
+
+// The following are default, do-nothing, implementations of the
+// hook methods normally provided by a derived class. We provide
+// default implementations rather than no implementation so that
+// a derived class needs to implement only the hooks that it needs
+// to use.
+
+// Process a compilation unit and parse its child DIE.
+
+void
+Dwarf_info_reader::visit_compilation_unit(off_t, off_t, Dwarf_die*)
+{
+}
+
+// Process a type unit and parse its child DIE.
+
+void
+Dwarf_info_reader::visit_type_unit(off_t, off_t, uint64_t, Dwarf_die*)
+{
+}
+
+// class Sized_dwarf_line_info
+
struct LineStateMachine
{
int file_num;
@@ -62,12 +1426,15 @@ ResetLineStateMachine(struct LineStateMachine* lsm, bool default_is_stmt)
}
template<int size, bool big_endian>
-Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info(Object* object,
- unsigned int read_shndx)
- : data_valid_(false), buffer_(NULL), symtab_buffer_(NULL),
- directories_(), files_(), current_header_index_(-1)
+Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info(
+ Object* object,
+ unsigned int read_shndx)
+ : data_valid_(false), buffer_(NULL), buffer_start_(NULL),
+ reloc_mapper_(NULL), symtab_buffer_(NULL), directories_(), files_(),
+ current_header_index_(-1)
{
unsigned int debug_shndx;
+
for (debug_shndx = 1; debug_shndx < object->shnum(); ++debug_shndx)
{
// FIXME: do this more efficiently: section_name() isn't super-fast
@@ -75,8 +1442,12 @@ Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info(Object* object,
if (name == ".debug_line" || name == ".zdebug_line")
{
section_size_type buffer_size;
- this->buffer_ = object->section_contents(debug_shndx, &buffer_size,
- false);
+ bool is_new = false;
+ this->buffer_ = object->decompressed_section_contents(debug_shndx,
+ &buffer_size,
+ &is_new);
+ if (is_new)
+ this->buffer_start_ = this->buffer_;
this->buffer_end_ = this->buffer_ + buffer_size;
break;
}
@@ -84,59 +1455,48 @@ Sized_dwarf_line_info<size, big_endian>::Sized_dwarf_line_info(Object* object,
if (this->buffer_ == NULL)
return;
- section_size_type uncompressed_size = 0;
- unsigned char* uncompressed_data = NULL;
- if (object->section_is_compressed(debug_shndx, &uncompressed_size))
- {
- uncompressed_data = new unsigned char[uncompressed_size];
- if (!decompress_input_section(this->buffer_,
- this->buffer_end_ - this->buffer_,
- uncompressed_data,
- uncompressed_size))
- object->error(_("could not decompress section %s"),
- object->section_name(debug_shndx).c_str());
- this->buffer_ = uncompressed_data;
- this->buffer_end_ = this->buffer_ + uncompressed_size;
- }
-
// Find the relocation section for ".debug_line".
// We expect these for relobjs (.o's) but not dynobjs (.so's).
- bool got_relocs = false;
- for (unsigned int reloc_shndx = 0;
- reloc_shndx < object->shnum();
- ++reloc_shndx)
+ unsigned int reloc_shndx = 0;
+ for (unsigned int i = 0; i < object->shnum(); ++i)
{
- unsigned int reloc_sh_type = object->section_type(reloc_shndx);
+ unsigned int reloc_sh_type = object->section_type(i);
if ((reloc_sh_type == elfcpp::SHT_REL
|| reloc_sh_type == elfcpp::SHT_RELA)
- && object->section_info(reloc_shndx) == debug_shndx)
+ && object->section_info(i) == debug_shndx)
{
- got_relocs = this->track_relocs_.initialize(object, reloc_shndx,
- reloc_sh_type);
+ reloc_shndx = i;
this->track_relocs_type_ = reloc_sh_type;
break;
}
}
// Finally, we need the symtab section to interpret the relocs.
- if (got_relocs)
+ if (reloc_shndx != 0)
{
unsigned int symtab_shndx;
for (symtab_shndx = 0; symtab_shndx < object->shnum(); ++symtab_shndx)
if (object->section_type(symtab_shndx) == elfcpp::SHT_SYMTAB)
{
- this->symtab_buffer_ = object->section_contents(
- symtab_shndx, &this->symtab_buffer_size_, false);
+ this->symtab_buffer_ = object->section_contents(
+ symtab_shndx, &this->symtab_buffer_size_, false);
break;
}
if (this->symtab_buffer_ == NULL)
return;
}
+ this->reloc_mapper_ =
+ new Sized_elf_reloc_mapper<size, big_endian>(object,
+ this->symtab_buffer_,
+ this->symtab_buffer_size_);
+ if (!this->reloc_mapper_->initialize(reloc_shndx, this->track_relocs_type_))
+ return;
+
// Now that we have successfully read all the data, parse the debug
// info.
this->data_valid_ = true;
- this->read_line_mappings(object, read_shndx);
+ this->read_line_mappings(read_shndx);
}
// Read the DWARF header.
@@ -422,17 +1782,16 @@ Sized_dwarf_line_info<size, big_endian>::process_one_opcode(
start += templen;
uint64_t dirindex = read_unsigned_LEB_128(start, &templen);
- oplen += templen;
if (dirindex >= this->directories_.back().size())
dirindex = 0;
int dirindexi = static_cast<int>(dirindex);
- read_unsigned_LEB_128(start, &templen); // mod_time
- oplen += templen;
-
- read_unsigned_LEB_128(start, &templen); // filelength
- oplen += templen;
+ // This opcode takes two additional ULEB128 parameters
+ // (mod_time and filelength), but we don't use those
+ // values. Because OPLEN already tells us how far to
+ // skip to the next opcode, we don't need to read
+ // them at all.
this->files_.back().push_back(std::make_pair(dirindexi,
filename));
@@ -514,51 +1873,28 @@ Sized_dwarf_line_info<size, big_endian>::read_lines(unsigned const char* lineptr
return lengthstart + header_.total_length;
}
-// Looks in the symtab to see what section a symbol is in.
-
-template<int size, bool big_endian>
-unsigned int
-Sized_dwarf_line_info<size, big_endian>::symbol_section(
- Object* object,
- unsigned int sym,
- typename elfcpp::Elf_types<size>::Elf_Addr* value,
- bool* is_ordinary)
-{
- const int symsize = elfcpp::Elf_sizes<size>::sym_size;
- gold_assert(sym * symsize < this->symtab_buffer_size_);
- elfcpp::Sym<size, big_endian> elfsym(this->symtab_buffer_ + sym * symsize);
- *value = elfsym.get_st_value();
- return object->adjust_sym_shndx(sym, elfsym.get_st_shndx(), is_ordinary);
-}
-
// Read the relocations into a Reloc_map.
template<int size, bool big_endian>
void
-Sized_dwarf_line_info<size, big_endian>::read_relocs(Object* object)
+Sized_dwarf_line_info<size, big_endian>::read_relocs()
{
if (this->symtab_buffer_ == NULL)
return;
- typename elfcpp::Elf_types<size>::Elf_Addr value;
+ off_t value;
off_t reloc_offset;
- while ((reloc_offset = this->track_relocs_.next_offset()) != -1)
+ while ((reloc_offset = this->reloc_mapper_->next_offset()) != -1)
{
- const unsigned int sym = this->track_relocs_.next_symndx();
-
- bool is_ordinary;
- const unsigned int shndx = this->symbol_section(object, sym, &value,
- &is_ordinary);
+ const unsigned int shndx =
+ this->reloc_mapper_->get_reloc_target(reloc_offset, &value);
// There is no reason to record non-ordinary section indexes, or
// SHN_UNDEF, because they will never match the real section.
- if (is_ordinary && shndx != elfcpp::SHN_UNDEF)
- {
- value += this->track_relocs_.next_addend();
- this->reloc_map_[reloc_offset] = std::make_pair(shndx, value);
- }
+ if (shndx != 0)
+ this->reloc_map_[reloc_offset] = std::make_pair(shndx, value);
- this->track_relocs_.advance(reloc_offset + 1);
+ this->reloc_mapper_->advance(reloc_offset + 1);
}
}
@@ -566,12 +1902,11 @@ Sized_dwarf_line_info<size, big_endian>::read_relocs(Object* object)
template<int size, bool big_endian>
void
-Sized_dwarf_line_info<size, big_endian>::read_line_mappings(Object* object,
- unsigned int shndx)
+Sized_dwarf_line_info<size, big_endian>::read_line_mappings(unsigned int shndx)
{
gold_assert(this->data_valid_ == true);
- this->read_relocs(object);
+ this->read_relocs();
while (this->buffer_ < this->buffer_end_)
{
const unsigned char* lineptr = this->buffer_;
@@ -775,7 +2110,7 @@ Sized_dwarf_line_info<size, big_endian>::format_file_lineno(
gold_assert(loc.header_num < static_cast<int>(this->files_.size()));
gold_assert(loc.file_num
- < static_cast<int>(this->files_[loc.header_num].size()));
+ < static_cast<unsigned int>(this->files_[loc.header_num].size()));
const std::pair<int, std::string>& filename_pair
= this->files_[loc.header_num][loc.file_num];
const std::string& filename = filename_pair.second;
diff --git a/binutils-2.22/gold/dwarf_reader.h b/binutils-2.22/gold/dwarf_reader.h
index 3f92dd3..de5722b 100644
--- a/binutils-2.22/gold/dwarf_reader.h
+++ b/binutils-2.22/gold/dwarf_reader.h
@@ -1,6 +1,6 @@
// dwarf_reader.h -- parse dwarf2/3 debug information for gold -*- C++ -*-
-// Copyright 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -26,6 +26,7 @@
#include <vector>
#include <map>
#include <limits.h>
+#include <sys/types.h>
#include "elfcpp.h"
#include "elfcpp_swap.h"
@@ -35,10 +36,818 @@
namespace gold
{
-template<int size, bool big_endian>
-class Track_relocs;
+class Dwarf_info_reader;
struct LineStateMachine;
+// This class is used to extract the section index and offset of
+// the target of a relocation for a given offset within the section.
+
+class Elf_reloc_mapper
+{
+ public:
+ Elf_reloc_mapper()
+ { }
+
+ virtual
+ ~Elf_reloc_mapper()
+ { }
+
+ // Initialize the relocation tracker for section RELOC_SHNDX.
+ bool
+ initialize(unsigned int reloc_shndx, unsigned int reloc_type)
+ { return this->do_initialize(reloc_shndx, reloc_type); }
+
+ // Return the next reloc_offset.
+ off_t
+ next_offset()
+ { return this->do_next_offset(); }
+
+ // Advance to the next relocation past OFFSET.
+ void
+ advance(off_t offset)
+ { this->do_advance(offset); }
+
+ // Return the section index and offset within the section of the target
+ // of the relocation for RELOC_OFFSET in the referring section.
+ unsigned int
+ get_reloc_target(off_t reloc_offset, off_t* target_offset)
+ { return this->do_get_reloc_target(reloc_offset, target_offset); }
+
+ // Checkpoint the current position in the reloc section.
+ uint64_t
+ checkpoint() const
+ { return this->do_checkpoint(); }
+
+ // Reset the current position to the CHECKPOINT.
+ void
+ reset(uint64_t checkpoint)
+ { this->do_reset(checkpoint); }
+
+ protected:
+ virtual bool
+ do_initialize(unsigned int, unsigned int) = 0;
+
+ // Return the next reloc_offset.
+ virtual off_t
+ do_next_offset() = 0;
+
+ // Advance to the next relocation past OFFSET.
+ virtual void
+ do_advance(off_t offset) = 0;
+
+ virtual unsigned int
+ do_get_reloc_target(off_t reloc_offset, off_t* target_offset) = 0;
+
+ // Checkpoint the current position in the reloc section.
+ virtual uint64_t
+ do_checkpoint() const = 0;
+
+ // Reset the current position to the CHECKPOINT.
+ virtual void
+ do_reset(uint64_t checkpoint) = 0;
+};
+
+template<int size, bool big_endian>
+class Sized_elf_reloc_mapper : public Elf_reloc_mapper
+{
+ public:
+ Sized_elf_reloc_mapper(Object* object, const unsigned char* symtab,
+ off_t symtab_size)
+ : object_(object), symtab_(symtab), symtab_size_(symtab_size),
+ reloc_type_(0), track_relocs_()
+ { }
+
+ protected:
+ bool
+ do_initialize(unsigned int reloc_shndx, unsigned int reloc_type);
+
+ // Return the next reloc_offset.
+ virtual off_t
+ do_next_offset()
+ { return this->track_relocs_.next_offset(); }
+
+ // Advance to the next relocation past OFFSET.
+ virtual void
+ do_advance(off_t offset)
+ { this->track_relocs_.advance(offset); }
+
+ unsigned int
+ do_get_reloc_target(off_t reloc_offset, off_t* target_offset);
+
+ // Checkpoint the current position in the reloc section.
+ uint64_t
+ do_checkpoint() const
+ { return this->track_relocs_.checkpoint(); }
+
+ // Reset the current position to the CHECKPOINT.
+ void
+ do_reset(uint64_t checkpoint)
+ { this->track_relocs_.reset(checkpoint); }
+
+ private:
+ typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
+
+ // Return the section index of symbol SYMNDX, and copy its value to *VALUE.
+ // Set *IS_ORDINARY true if the section index is an ordinary section index.
+ unsigned int
+ symbol_section(unsigned int symndx, Address* value, bool* is_ordinary);
+
+ // The object file.
+ Object* object_;
+ // The ELF symbol table.
+ const unsigned char* symtab_;
+ // The size of the ELF symbol table.
+ off_t symtab_size_;
+ // Type of the relocation section (SHT_REL or SHT_RELA).
+ unsigned int reloc_type_;
+ // Relocations for the referring section.
+ Track_relocs<size, big_endian> track_relocs_;
+};
+
+// This class is used to read the abbreviations table from the
+// .debug_abbrev section of the object file.
+
+class Dwarf_abbrev_table
+{
+ public:
+ // An attribute list entry.
+ struct Attribute
+ {
+ Attribute(unsigned int a, unsigned int f)
+ : attr(a), form(f)
+ { }
+ unsigned int attr;
+ unsigned int form;
+ };
+
+ // An abbrev code entry.
+ struct Abbrev_code
+ {
+ Abbrev_code(unsigned int t, bool hc)
+ : tag(t), has_children(hc), has_sibling_attribute(false), attributes()
+ {
+ this->attributes.reserve(10);
+ }
+
+ void
+ add_attribute(unsigned int attr, unsigned int form)
+ {
+ this->attributes.push_back(Attribute(attr, form));
+ }
+
+ // The DWARF tag.
+ unsigned int tag;
+ // True if the DIE has children.
+ bool has_children : 1;
+ // True if the DIE has a sibling attribute.
+ bool has_sibling_attribute : 1;
+ // The list of attributes and forms.
+ std::vector<Attribute> attributes;
+ };
+
+ Dwarf_abbrev_table()
+ : abbrev_shndx_(0), abbrev_offset_(0), buffer_(NULL), buffer_end_(NULL),
+ owns_buffer_(false), buffer_pos_(NULL), high_abbrev_codes_()
+ {
+ memset(this->low_abbrev_codes_, 0, sizeof(this->low_abbrev_codes_));
+ }
+
+ ~Dwarf_abbrev_table()
+ {
+ if (this->owns_buffer_ && this->buffer_ != NULL)
+ delete[] this->buffer_;
+ this->clear_abbrev_codes();
+ }
+
+ // Read the abbrev table from an object file.
+ bool
+ read_abbrevs(Relobj* object,
+ unsigned int abbrev_shndx,
+ off_t abbrev_offset)
+ {
+ // If we've already read this abbrev table, return immediately.
+ if (this->abbrev_shndx_ > 0
+ && this->abbrev_shndx_ == abbrev_shndx
+ && this->abbrev_offset_ == abbrev_offset)
+ return true;
+ return this->do_read_abbrevs(object, abbrev_shndx, abbrev_offset);
+ }
+
+ // Return the abbrev code entry for CODE. This is a fast path for
+ // abbrev codes that are in the direct lookup table. If not found
+ // there, we call do_get_abbrev() to do the hard work.
+ const Abbrev_code*
+ get_abbrev(unsigned int code)
+ {
+ if (code < this->low_abbrev_code_max_
+ && this->low_abbrev_codes_[code] != NULL)
+ return this->low_abbrev_codes_[code];
+ return this->do_get_abbrev(code);
+ }
+
+ private:
+ // Read the abbrev table from an object file.
+ bool
+ do_read_abbrevs(Relobj* object,
+ unsigned int abbrev_shndx,
+ off_t abbrev_offset);
+
+ // Lookup the abbrev code entry for CODE.
+ const Abbrev_code*
+ do_get_abbrev(unsigned int code);
+
+ // Store an abbrev code entry for CODE.
+ void
+ store_abbrev(unsigned int code, const Abbrev_code* entry)
+ {
+ if (code < this->low_abbrev_code_max_)
+ this->low_abbrev_codes_[code] = entry;
+ else
+ this->high_abbrev_codes_[code] = entry;
+ }
+
+ // Clear the abbrev code table and release the memory it uses.
+ void
+ clear_abbrev_codes();
+
+ typedef Unordered_map<unsigned int, const Abbrev_code*> Abbrev_code_table;
+
+ // The section index of the current abbrev table.
+ unsigned int abbrev_shndx_;
+ // The offset within the section of the current abbrev table.
+ off_t abbrev_offset_;
+ // The buffer containing the .debug_abbrev section.
+ const unsigned char* buffer_;
+ const unsigned char* buffer_end_;
+ // True if this object owns the buffer and needs to delete it.
+ bool owns_buffer_;
+ // Pointer to the current position in the buffer.
+ const unsigned char* buffer_pos_;
+ // The table of abbrev codes.
+ // We use a direct-lookup array for low abbrev codes,
+ // and store the rest in a hash table.
+ static const unsigned int low_abbrev_code_max_ = 256;
+ const Abbrev_code* low_abbrev_codes_[low_abbrev_code_max_];
+ Abbrev_code_table high_abbrev_codes_;
+};
+
+// A DWARF range list. The start and end offsets are relative
+// to the input section SHNDX. Each range must lie entirely
+// within a single section.
+
+class Dwarf_range_list
+{
+ public:
+ struct Range
+ {
+ Range(unsigned int a_shndx, off_t a_start, off_t a_end)
+ : shndx(a_shndx), start(a_start), end(a_end)
+ { }
+
+ unsigned int shndx;
+ off_t start;
+ off_t end;
+ };
+
+ Dwarf_range_list()
+ : range_list_()
+ { }
+
+ void
+ add(unsigned int shndx, off_t start, off_t end)
+ { this->range_list_.push_back(Range(shndx, start, end)); }
+
+ size_t
+ size() const
+ { return this->range_list_.size(); }
+
+ const Range&
+ operator[](off_t i) const
+ { return this->range_list_[i]; }
+
+ private:
+ std::vector<Range> range_list_;
+};
+
+// This class is used to read the ranges table from the
+// .debug_ranges section of the object file.
+
+class Dwarf_ranges_table
+{
+ public:
+ Dwarf_ranges_table()
+ : ranges_shndx_(0), ranges_buffer_(NULL), ranges_buffer_end_(NULL),
+ owns_ranges_buffer_(false), ranges_reloc_mapper_(NULL),
+ output_section_offset_(0)
+ { }
+
+ ~Dwarf_ranges_table()
+ {
+ if (this->owns_ranges_buffer_ && this->ranges_buffer_ != NULL)
+ delete[] this->ranges_buffer_;
+ if (this->ranges_reloc_mapper_ != NULL)
+ delete this->ranges_reloc_mapper_;
+ }
+
+ // Read the ranges table from an object file.
+ bool
+ read_ranges_table(Relobj* object,
+ const unsigned char* symtab,
+ off_t symtab_size,
+ unsigned int ranges_shndx);
+
+ // Read the range table from an object file.
+ Dwarf_range_list*
+ read_range_list(Relobj* object,
+ const unsigned char* symtab,
+ off_t symtab_size,
+ unsigned int address_size,
+ unsigned int ranges_shndx,
+ off_t ranges_offset);
+
+ private:
+ // The section index of the ranges table.
+ unsigned int ranges_shndx_;
+ // The buffer containing the .debug_ranges section.
+ const unsigned char* ranges_buffer_;
+ const unsigned char* ranges_buffer_end_;
+ // True if this object owns the buffer and needs to delete it.
+ bool owns_ranges_buffer_;
+ // Relocation mapper for the .debug_ranges section.
+ Elf_reloc_mapper* ranges_reloc_mapper_;
+ // For incremental update links, this will hold the offset of the
+ // input section within the output section. Offsets read from
+ // relocated data will be relative to the output section, and need
+ // to be corrected before reading data from the input section.
+ uint64_t output_section_offset_;
+};
+
+// This class is used to read the pubnames and pubtypes tables from the
+// .debug_pubnames and .debug_pubtypes sections of the object file.
+
+class Dwarf_pubnames_table
+{
+ public:
+ Dwarf_pubnames_table(bool is_pubtypes)
+ : buffer_(NULL), buffer_end_(NULL), owns_buffer_(false),
+ offset_size_(0), pinfo_(NULL), is_pubtypes_(is_pubtypes),
+ output_section_offset_(0)
+ { }
+
+ ~Dwarf_pubnames_table()
+ {
+ if (this->owns_buffer_ && this->buffer_ != NULL)
+ delete[] this->buffer_;
+ }
+
+ // Read the pubnames section SHNDX from the object file.
+ bool
+ read_section(Relobj* object, unsigned int shndx);
+
+ // Read the header for the set at OFFSET.
+ bool
+ read_header(off_t offset);
+
+ // Read the next name from the set.
+ const char*
+ next_name();
+
+ private:
+ // The buffer containing the .debug_ranges section.
+ const unsigned char* buffer_;
+ const unsigned char* buffer_end_;
+ // True if this object owns the buffer and needs to delete it.
+ bool owns_buffer_;
+ // The size of a DWARF offset for the current set.
+ unsigned int offset_size_;
+ // The current position within the buffer.
+ const unsigned char* pinfo_;
+ // TRUE if this is a .debug_pubtypes section.
+ bool is_pubtypes_;
+ // For incremental update links, this will hold the offset of the
+ // input section within the output section. Offsets read from
+ // relocated data will be relative to the output section, and need
+ // to be corrected before reading data from the input section.
+ uint64_t output_section_offset_;
+};
+
+// This class represents a DWARF Debug Info Entry (DIE).
+
+class Dwarf_die
+{
+ public:
+ // An attribute value.
+ struct Attribute_value
+ {
+ unsigned int attr;
+ unsigned int form;
+ union
+ {
+ int64_t intval;
+ uint64_t uintval;
+ const char* stringval;
+ const unsigned char* blockval;
+ off_t refval;
+ } val;
+ union
+ {
+ // Section index for reference forms.
+ unsigned int shndx;
+ // Block length for block forms.
+ unsigned int blocklen;
+ // Attribute offset for DW_FORM_strp.
+ unsigned int attr_off;
+ } aux;
+ };
+
+ // A list of attribute values.
+ typedef std::vector<Attribute_value> Attributes;
+
+ Dwarf_die(Dwarf_info_reader* dwinfo,
+ off_t die_offset,
+ Dwarf_die* parent);
+
+ // Return the DWARF tag for this DIE.
+ unsigned int
+ tag() const
+ {
+ if (this->abbrev_code_ == NULL)
+ return 0;
+ return this->abbrev_code_->tag;
+ }
+
+ // Return true if this DIE has children.
+ bool
+ has_children() const
+ {
+ gold_assert(this->abbrev_code_ != NULL);
+ return this->abbrev_code_->has_children;
+ }
+
+ // Return true if this DIE has a sibling attribute.
+ bool
+ has_sibling_attribute() const
+ {
+ gold_assert(this->abbrev_code_ != NULL);
+ return this->abbrev_code_->has_sibling_attribute;
+ }
+
+ // Return the value of attribute ATTR.
+ const Attribute_value*
+ attribute(unsigned int attr);
+
+ // Return the value of the DW_AT_name attribute.
+ const char*
+ name()
+ {
+ if (this->name_ == NULL)
+ this->set_name();
+ return this->name_;
+ }
+
+ // Return the value of the DW_AT_linkage_name
+ // or DW_AT_MIPS_linkage_name attribute.
+ const char*
+ linkage_name()
+ {
+ if (this->linkage_name_ == NULL)
+ this->set_linkage_name();
+ return this->linkage_name_;
+ }
+
+ // Return the value of the DW_AT_specification attribute.
+ off_t
+ specification()
+ {
+ if (!this->attributes_read_)
+ this->read_attributes();
+ return this->specification_;
+ }
+
+ // Return the value of the DW_AT_abstract_origin attribute.
+ off_t
+ abstract_origin()
+ {
+ if (!this->attributes_read_)
+ this->read_attributes();
+ return this->abstract_origin_;
+ }
+
+ // Return the value of attribute ATTR as a string.
+ const char*
+ string_attribute(unsigned int attr);
+
+ // Return the value of attribute ATTR as an integer.
+ int64_t
+ int_attribute(unsigned int attr);
+
+ // Return the value of attribute ATTR as an unsigned integer.
+ uint64_t
+ uint_attribute(unsigned int attr);
+
+ // Return the value of attribute ATTR as a reference.
+ off_t
+ ref_attribute(unsigned int attr, unsigned int* shndx);
+
+ // Return the value of attribute ATTR as a address.
+ off_t
+ address_attribute(unsigned int attr, unsigned int* shndx);
+
+ // Return the value of attribute ATTR as a flag.
+ bool
+ flag_attribute(unsigned int attr)
+ { return this->int_attribute(attr) != 0; }
+
+ // Return true if this DIE is a declaration.
+ bool
+ is_declaration()
+ { return this->flag_attribute(elfcpp::DW_AT_declaration); }
+
+ // Return the parent of this DIE.
+ Dwarf_die*
+ parent() const
+ { return this->parent_; }
+
+ // Return the offset of this DIE.
+ off_t
+ offset() const
+ { return this->die_offset_; }
+
+ // Return the offset of this DIE's first child.
+ off_t
+ child_offset();
+
+ // Set the offset of this DIE's next sibling.
+ void
+ set_sibling_offset(off_t sibling_offset)
+ { this->sibling_offset_ = sibling_offset; }
+
+ // Return the offset of this DIE's next sibling.
+ off_t
+ sibling_offset();
+
+ private:
+ typedef Dwarf_abbrev_table::Abbrev_code Abbrev_code;
+
+ // Read all the attributes of the DIE.
+ bool
+ read_attributes();
+
+ // Set the name of the DIE if present.
+ void
+ set_name();
+
+ // Set the linkage name if present.
+ void
+ set_linkage_name();
+
+ // Skip all the attributes of the DIE and return the offset
+ // of the next DIE.
+ off_t
+ skip_attributes();
+
+ // The Dwarf_info_reader, for reading attributes.
+ Dwarf_info_reader* dwinfo_;
+ // The parent of this DIE.
+ Dwarf_die* parent_;
+ // Offset of this DIE within its compilation unit.
+ off_t die_offset_;
+ // Offset of the first attribute, relative to the beginning of the DIE.
+ off_t attr_offset_;
+ // Offset of the first child, relative to the compilation unit.
+ off_t child_offset_;
+ // Offset of the next sibling, relative to the compilation unit.
+ off_t sibling_offset_;
+ // The abbreviation table entry.
+ const Abbrev_code* abbrev_code_;
+ // The list of attributes.
+ Attributes attributes_;
+ // True if the attributes have been read.
+ bool attributes_read_;
+ // The following fields hold common attributes to avoid a linear
+ // search through the attribute list.
+ // The DIE name (DW_AT_name).
+ const char* name_;
+ // Offset of the name in the string table (for DW_FORM_strp).
+ off_t name_off_;
+ // The linkage name (DW_AT_linkage_name or DW_AT_MIPS_linkage_name).
+ const char* linkage_name_;
+ // Offset of the linkage name in the string table (for DW_FORM_strp).
+ off_t linkage_name_off_;
+ // Section index of the string table (for DW_FORM_strp).
+ unsigned int string_shndx_;
+ // The value of a DW_AT_specification attribute.
+ off_t specification_;
+ // The value of a DW_AT_abstract_origin attribute.
+ off_t abstract_origin_;
+};
+
+// This class is used to read the debug info from the .debug_info
+// or .debug_types sections. This is a base class that implements
+// the generic parsing of the compilation unit header and DIE
+// structure. The parse() method parses the entire section, and
+// calls the various visit_xxx() methods for each header. Clients
+// should derive a new class from this one and implement the
+// visit_compilation_unit() and visit_type_unit() functions.
+
+class Dwarf_info_reader
+{
+ public:
+ Dwarf_info_reader(bool is_type_unit,
+ Relobj* object,
+ const unsigned char* symtab,
+ off_t symtab_size,
+ unsigned int shndx,
+ unsigned int reloc_shndx,
+ unsigned int reloc_type)
+ : is_type_unit_(is_type_unit), object_(object), symtab_(symtab),
+ symtab_size_(symtab_size), shndx_(shndx), reloc_shndx_(reloc_shndx),
+ reloc_type_(reloc_type), string_shndx_(0), buffer_(NULL),
+ buffer_end_(NULL), cu_offset_(0), cu_length_(0), offset_size_(0),
+ address_size_(0), cu_version_(0), type_signature_(0), type_offset_(0),
+ abbrev_table_(), reloc_mapper_(NULL), string_buffer_(NULL),
+ string_buffer_end_(NULL), owns_string_buffer_(false),
+ string_output_section_offset_(0)
+ { }
+
+ virtual
+ ~Dwarf_info_reader()
+ {
+ if (this->reloc_mapper_ != NULL)
+ delete this->reloc_mapper_;
+ if (this->owns_string_buffer_ && this->string_buffer_ != NULL)
+ delete[] this->string_buffer_;
+ }
+
+ // Begin parsing the debug info. This calls visit_compilation_unit()
+ // or visit_type_unit() for each compilation or type unit found in the
+ // section, and visit_die() for each top-level DIE.
+ void
+ parse();
+
+ // Return the abbrev code entry for a CODE.
+ const Dwarf_abbrev_table::Abbrev_code*
+ get_abbrev(unsigned int code)
+ { return this->abbrev_table_.get_abbrev(code); }
+
+ // Return a pointer to the DWARF info buffer at OFFSET.
+ const unsigned char*
+ buffer_at_offset(off_t offset) const
+ {
+ const unsigned char* p = this->buffer_ + this->cu_offset_ + offset;
+ if (this->check_buffer(p + 1))
+ return p;
+ return NULL;
+ }
+
+ // Look for a relocation at offset ATTR_OFF in the dwarf info,
+ // and return the section index and offset of the target.
+ unsigned int
+ lookup_reloc(off_t attr_off, off_t* target_off);
+
+ // Return a string from the DWARF string table.
+ const char*
+ get_string(off_t str_off, unsigned int string_shndx);
+
+ // Return the size of a DWARF offset.
+ unsigned int
+ offset_size() const
+ { return this->offset_size_; }
+
+ // Return the size of an address.
+ unsigned int
+ address_size() const
+ { return this->address_size_; }
+
+ protected:
+ // Begin parsing the debug info. This calls visit_compilation_unit()
+ // or visit_type_unit() for each compilation or type unit found in the
+ // section, and visit_die() for each top-level DIE.
+ template<bool big_endian>
+ void
+ do_parse();
+
+ // The following methods are hooks that are meant to be implemented
+ // by a derived class. A default, do-nothing, implementation of
+ // each is provided for this base class.
+
+ // Visit a compilation unit.
+ virtual void
+ visit_compilation_unit(off_t cu_offset, off_t cu_length, Dwarf_die* root_die);
+
+ // Visit a type unit.
+ virtual void
+ visit_type_unit(off_t tu_offset, off_t type_offset, uint64_t signature,
+ Dwarf_die* root_die);
+
+ // Read the range table.
+ Dwarf_range_list*
+ read_range_list(unsigned int ranges_shndx, off_t ranges_offset)
+ {
+ return this->ranges_table_.read_range_list(this->object_,
+ this->symtab_,
+ this->symtab_size_,
+ this->address_size_,
+ ranges_shndx,
+ ranges_offset);
+ }
+
+ // Return the object.
+ Relobj*
+ object() const
+ { return this->object_; }
+
+ // Return a pointer to the object file's ELF symbol table.
+ const unsigned char*
+ symtab() const
+ { return this->symtab_; }
+
+ // Return the size of the object file's ELF symbol table.
+ off_t
+ symtab_size() const
+ { return this->symtab_size_; }
+
+ // Checkpoint the relocation tracker.
+ uint64_t
+ get_reloc_checkpoint() const
+ { return this->reloc_mapper_->checkpoint(); }
+
+ // Reset the relocation tracker to the CHECKPOINT.
+ void
+ reset_relocs(uint64_t checkpoint)
+ { this->reloc_mapper_->reset(checkpoint); }
+
+ private:
+ // Check that P is within the bounds of the current section.
+ bool
+ check_buffer(const unsigned char* p) const;
+
+ // Read the DWARF string table.
+ bool
+ read_string_table(unsigned int string_shndx)
+ {
+ // If we've already read this string table, return immediately.
+ if (this->string_shndx_ > 0 && this->string_shndx_ == string_shndx)
+ return true;
+ if (string_shndx == 0 && this->string_shndx_ > 0)
+ return true;
+ return this->do_read_string_table(string_shndx);
+ }
+
+ bool
+ do_read_string_table(unsigned int string_shndx);
+
+ // True if this is a type unit; false for a compilation unit.
+ bool is_type_unit_;
+ // The object containing the .debug_info or .debug_types input section.
+ Relobj* object_;
+ // The ELF symbol table.
+ const unsigned char* symtab_;
+ // The size of the ELF symbol table.
+ off_t symtab_size_;
+ // Index of the .debug_info or .debug_types section.
+ unsigned int shndx_;
+ // Index of the relocation section.
+ unsigned int reloc_shndx_;
+ // Type of the relocation section (SHT_REL or SHT_RELA).
+ unsigned int reloc_type_;
+ // Index of the .debug_str section.
+ unsigned int string_shndx_;
+ // The buffer for the debug info.
+ const unsigned char* buffer_;
+ const unsigned char* buffer_end_;
+ // Offset of the current compilation unit.
+ off_t cu_offset_;
+ // Length of the current compilation unit.
+ off_t cu_length_;
+ // Size of a DWARF offset for the current compilation unit.
+ unsigned int offset_size_;
+ // Size of an address for the target architecture.
+ unsigned int address_size_;
+ // Compilation unit version number.
+ unsigned int cu_version_;
+ // Type signature (for a type unit).
+ uint64_t type_signature_;
+ // Offset from the type unit header to the type DIE (for a type unit).
+ off_t type_offset_;
+ // Abbreviations table for current compilation unit.
+ Dwarf_abbrev_table abbrev_table_;
+ // Ranges table for the current compilation unit.
+ Dwarf_ranges_table ranges_table_;
+ // Relocation mapper for the section.
+ Elf_reloc_mapper* reloc_mapper_;
+ // The buffer for the debug string table.
+ const char* string_buffer_;
+ const char* string_buffer_end_;
+ // True if this object owns the buffer and needs to delete it.
+ bool owns_string_buffer_;
+ // For incremental update links, this will hold the offset of the
+ // input .debug_str section within the output section. Offsets read
+ // from relocated data will be relative to the output section, and need
+ // to be corrected before reading data from the input section.
+ uint64_t string_output_section_offset_;
+};
+
// We can't do better than to keep the offsets in a sorted vector.
// Here, offset is the key, and file_num/line_num is the value.
struct Offset_to_lineno_entry
@@ -120,6 +929,13 @@ class Sized_dwarf_line_info : public Dwarf_line_info
// information that pertains to the specified section.
Sized_dwarf_line_info(Object* object, unsigned int read_shndx = -1U);
+ virtual
+ ~Sized_dwarf_line_info()
+ {
+ if (this->buffer_start_ != NULL)
+ delete[] this->buffer_start_;
+ }
+
private:
std::string
do_addr2line(unsigned int shndx, off_t offset,
@@ -133,18 +949,12 @@ class Sized_dwarf_line_info : public Dwarf_line_info
// If SHNDX is non-negative, only store debug information that
// pertains to the specified section.
void
- read_line_mappings(Object*, unsigned int shndx);
+ read_line_mappings(unsigned int shndx);
// Reads the relocation section associated with .debug_line and
// stores relocation information in reloc_map_.
void
- read_relocs(Object*);
-
- // Looks in the symtab to see what section a symbol is in.
- unsigned int
- symbol_section(Object*, unsigned int sym,
- typename elfcpp::Elf_types<size>::Elf_Addr* value,
- bool* is_ordinary);
+ read_relocs();
// Reads the DWARF2/3 header for this line info. Each takes as input
// a starting buffer position, and returns the ending position.
@@ -199,9 +1009,13 @@ class Sized_dwarf_line_info : public Dwarf_line_info
// the line info to read is.
const unsigned char* buffer_;
const unsigned char* buffer_end_;
+ // If the buffer was allocated temporarily, and therefore must be
+ // deallocated in the dtor, this contains a pointer to the start
+ // of the buffer.
+ const unsigned char* buffer_start_;
// This has relocations that point into buffer.
- Track_relocs<size, big_endian> track_relocs_;
+ Sized_elf_reloc_mapper<size, big_endian>* reloc_mapper_;
// The type of the reloc section in track_relocs_--SHT_REL or SHT_RELA.
unsigned int track_relocs_type_;
@@ -221,9 +1035,7 @@ class Sized_dwarf_line_info : public Dwarf_line_info
// A sorted map from offset of the relocation target to the shndx
// and addend for the relocation.
- typedef std::map<typename elfcpp::Elf_types<size>::Elf_Addr,
- std::pair<unsigned int,
- typename elfcpp::Elf_types<size>::Elf_Swxword> >
+ typedef std::map<off_t, std::pair<unsigned int, off_t> >
Reloc_map;
Reloc_map reloc_map_;
diff --git a/binutils-2.22/gold/dynobj.cc b/binutils-2.22/gold/dynobj.cc
index 4404a35..ac0c321 100644
--- a/binutils-2.22/gold/dynobj.cc
+++ b/binutils-2.22/gold/dynobj.cc
@@ -823,7 +823,7 @@ Sized_dynobj<size, big_endian>::do_get_global_symbol_counts(
&& (*p)->source() == Symbol::FROM_OBJECT
&& (*p)->object() == this
&& (*p)->is_defined()
- && (*p)->dynsym_index() != -1U)
+ && (*p)->has_dynsym_index())
++count;
*used = count;
}
diff --git a/binutils-2.22/gold/dynobj.h b/binutils-2.22/gold/dynobj.h
index 186b67c..e027485 100644
--- a/binutils-2.22/gold/dynobj.h
+++ b/binutils-2.22/gold/dynobj.h
@@ -208,9 +208,19 @@ class Sized_dynobj : public Dynobj
// Return a view of the contents of a section. Set *PLEN to the
// size.
- Object::Location
- do_section_contents(unsigned int shndx)
- { return this->elf_file_.section_contents(shndx); }
+ const unsigned char*
+ do_section_contents(unsigned int shndx, section_size_type* plen,
+ bool cache)
+ {
+ Location loc(this->elf_file_.section_contents(shndx));
+ *plen = convert_to_section_size_type(loc.data_size);
+ if (*plen == 0)
+ {
+ static const unsigned char empty[1] = { '\0' };
+ return empty;
+ }
+ return this->get_view(loc.file_offset, *plen, true, cache);
+ }
// Return section flags.
uint64_t
diff --git a/binutils-2.22/gold/ehframe.cc b/binutils-2.22/gold/ehframe.cc
index 59f44fb..1aaf346 100644
--- a/binutils-2.22/gold/ehframe.cc
+++ b/binutils-2.22/gold/ehframe.cc
@@ -1,6 +1,6 @@
// ehframe.cc -- handle exception frame sections for gold
-// Copyright 2006, 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2010, 2011, 2012 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
diff --git a/binutils-2.22/gold/expression.cc b/binutils-2.22/gold/expression.cc
index e527b5e..e31c151 100644
--- a/binutils-2.22/gold/expression.cc
+++ b/binutils-2.22/gold/expression.cc
@@ -1,6 +1,6 @@
// expression.cc -- expressions in linker scripts for gold
-// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -77,7 +77,7 @@ Expression::eval(const Symbol_table* symtab, const Layout* layout,
bool check_assertions)
{
return this->eval_maybe_dot(symtab, layout, check_assertions,
- false, 0, NULL, NULL, NULL);
+ false, 0, NULL, NULL, NULL, false);
}
// Evaluate an expression which may refer to the dot symbol.
@@ -87,11 +87,13 @@ Expression::eval_with_dot(const Symbol_table* symtab, const Layout* layout,
bool check_assertions, uint64_t dot_value,
Output_section* dot_section,
Output_section** result_section_pointer,
- uint64_t* result_alignment_pointer)
+ uint64_t* result_alignment_pointer,
+ bool is_section_dot_assignment)
{
return this->eval_maybe_dot(symtab, layout, check_assertions, true,
dot_value, dot_section, result_section_pointer,
- result_alignment_pointer);
+ result_alignment_pointer,
+ is_section_dot_assignment);
}
// Evaluate an expression which may or may not refer to the dot
@@ -102,7 +104,8 @@ Expression::eval_maybe_dot(const Symbol_table* symtab, const Layout* layout,
bool check_assertions, bool is_dot_available,
uint64_t dot_value, Output_section* dot_section,
Output_section** result_section_pointer,
- uint64_t* result_alignment_pointer)
+ uint64_t* result_alignment_pointer,
+ bool is_section_dot_assignment)
{
Expression_eval_info eei;
eei.symtab = symtab;
@@ -113,14 +116,24 @@ Expression::eval_maybe_dot(const Symbol_table* symtab, const Layout* layout,
eei.dot_section = dot_section;
// We assume the value is absolute, and only set this to a section
- // if we find a section relative reference.
+ // if we find a section-relative reference.
if (result_section_pointer != NULL)
*result_section_pointer = NULL;
eei.result_section_pointer = result_section_pointer;
eei.result_alignment_pointer = result_alignment_pointer;
- return this->value(&eei);
+ uint64_t val = this->value(&eei);
+
+ // If this is an assignment to dot within a section, and the value
+ // is absolute, treat it as a section-relative offset.
+ if (is_section_dot_assignment && *result_section_pointer == NULL)
+ {
+ gold_assert(dot_section != NULL);
+ val += dot_section->address();
+ *result_section_pointer = dot_section;
+ }
+ return val;
}
// A number.
@@ -257,7 +270,8 @@ class Unary_expression : public Expression
eei->dot_value,
eei->dot_section,
arg_section_pointer,
- eei->result_alignment_pointer);
+ eei->result_alignment_pointer,
+ false);
}
void
@@ -336,7 +350,8 @@ class Binary_expression : public Expression
eei->dot_value,
eei->dot_section,
section_pointer,
- alignment_pointer);
+ alignment_pointer,
+ false);
}
uint64_t
@@ -350,7 +365,8 @@ class Binary_expression : public Expression
eei->dot_value,
eei->dot_section,
section_pointer,
- alignment_pointer);
+ alignment_pointer,
+ false);
}
void
@@ -500,7 +516,8 @@ class Trinary_expression : public Expression
eei->dot_value,
eei->dot_section,
section_pointer,
- NULL);
+ NULL,
+ false);
}
uint64_t
@@ -514,7 +531,8 @@ class Trinary_expression : public Expression
eei->dot_value,
eei->dot_section,
section_pointer,
- alignment_pointer);
+ alignment_pointer,
+ false);
}
uint64_t
@@ -528,7 +546,8 @@ class Trinary_expression : public Expression
eei->dot_value,
eei->dot_section,
section_pointer,
- alignment_pointer);
+ alignment_pointer,
+ false);
}
void
diff --git a/binutils-2.22/gold/fileread.cc b/binutils-2.22/gold/fileread.cc
index 80ddfbc..c5dc320 100644
--- a/binutils-2.22/gold/fileread.cc
+++ b/binutils-2.22/gold/fileread.cc
@@ -329,6 +329,10 @@ inline File_read::View*
File_read::find_view(off_t start, section_size_type size,
unsigned int byteshift, File_read::View** vshifted) const
{
+ gold_assert(start <= this->size_
+ && (static_cast<unsigned long long>(size)
+ <= static_cast<unsigned long long>(this->size_ - start)));
+
if (vshifted != NULL)
*vshifted = NULL;
@@ -456,16 +460,9 @@ File_read::make_view(off_t start, section_size_type size,
unsigned int byteshift, bool cache)
{
gold_assert(size > 0);
-
- // Check that start and end of the view are within the file.
- if (start > this->size_
- || (static_cast<unsigned long long>(size)
- > static_cast<unsigned long long>(this->size_ - start)))
- gold_fatal(_("%s: attempt to map %lld bytes at offset %lld exceeds "
- "size of file; the file may be corrupt"),
- this->filename().c_str(),
- static_cast<long long>(size),
- static_cast<long long>(start));
+ gold_assert(start <= this->size_
+ && (static_cast<unsigned long long>(size)
+ <= static_cast<unsigned long long>(this->size_ - start)));
off_t poff = File_read::page_offset(start);
@@ -523,6 +520,16 @@ File_read::View*
File_read::find_or_make_view(off_t offset, off_t start,
section_size_type size, bool aligned, bool cache)
{
+ // Check that start and end of the view are within the file.
+ if (start > this->size_
+ || (static_cast<unsigned long long>(size)
+ > static_cast<unsigned long long>(this->size_ - start)))
+ gold_fatal(_("%s: attempt to map %lld bytes at offset %lld exceeds "
+ "size of file; the file may be corrupt"),
+ this->filename().c_str(),
+ static_cast<long long>(size),
+ static_cast<long long>(start));
+
unsigned int byteshift;
if (offset == 0)
byteshift = 0;
diff --git a/binutils-2.22/gold/freebsd.h b/binutils-2.22/gold/freebsd.h
index 175dd05..3bdedce 100644
--- a/binutils-2.22/gold/freebsd.h
+++ b/binutils-2.22/gold/freebsd.h
@@ -1,6 +1,6 @@
// freebsd.h -- FreeBSD support for gold -*- C++ -*-
-// Copyright 2009, 2011 Free Software Foundation, Inc.
+// Copyright 2009, 2011, 2012 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -48,14 +48,14 @@ class Target_selector_freebsd : public Target_selector
// If we see a FreeBSD input file, mark the output file as using
// FreeBSD.
virtual Target*
- do_recognize(int, int osabi, int)
+ do_recognize(Input_file*, off_t, int, int osabi, int)
{
Target* ret = this->instantiate_target();
if (osabi == elfcpp::ELFOSABI_FREEBSD)
ret->set_osabi(static_cast<elfcpp::ELFOSABI>(osabi));
return ret;
}
-
+
// Recognize two names.
virtual Target*
do_recognize_by_bfd_name(const char* name)
diff --git a/binutils-2.22/gold/gc.h b/binutils-2.22/gold/gc.h
index 4688781..56b5e74 100644
--- a/binutils-2.22/gold/gc.h
+++ b/binutils-2.22/gold/gc.h
@@ -1,6 +1,6 @@
// gc.h -- garbage collection of unused sections
-// Copyright 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
// Written by Sriraman Tallam <tmsriram@google.com>.
// This file is part of gold.
@@ -40,7 +40,7 @@ template<int size, bool big_endian>
class Sized_relobj_file;
template<int sh_type, int size, bool big_endian>
-class Reloc_types;
+struct Reloc_types;
class Output_section;
class General_options;
diff --git a/binutils-2.22/gold/gdb-index.cc b/binutils-2.22/gold/gdb-index.cc
new file mode 100644
index 0000000..6666988
--- /dev/null
+++ b/binutils-2.22/gold/gdb-index.cc
@@ -0,0 +1,1236 @@
+// gdb-index.cc -- generate .gdb_index section for fast debug lookup
+
+// Copyright 2012 Free Software Foundation, Inc.
+// Written by Cary Coutant <ccoutant@google.com>.
+
+// This file is part of gold.
+
+// 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.
+
+#include "gold.h"
+
+#include "gdb-index.h"
+#include "dwarf_reader.h"
+#include "dwarf.h"
+#include "object.h"
+#include "output.h"
+#include "demangle.h"
+
+namespace gold
+{
+
+const int gdb_index_version = 5;
+
+// Sizes of various records in the .gdb_index section.
+const int gdb_index_offset_size = 4;
+const int gdb_index_hdr_size = 6 * gdb_index_offset_size;
+const int gdb_index_cu_size = 16;
+const int gdb_index_tu_size = 24;
+const int gdb_index_addr_size = 16 + gdb_index_offset_size;
+const int gdb_index_sym_size = 2 * gdb_index_offset_size;
+
+// This class manages the hashed symbol table for the .gdb_index section.
+// It is essentially equivalent to the hashtab implementation in libiberty,
+// but is copied into gdb sources and here for compatibility because its
+// data structure is exposed on disk.
+
+template <typename T>
+class Gdb_hashtab
+{
+ public:
+ Gdb_hashtab()
+ : size_(0), capacity_(0), hashtab_(NULL)
+ { }
+
+ ~Gdb_hashtab()
+ {
+ for (size_t i = 0; i < this->capacity_; ++i)
+ if (this->hashtab_[i] != NULL)
+ delete this->hashtab_[i];
+ delete[] this->hashtab_;
+ }
+
+ // Add a symbol.
+ T*
+ add(T* symbol)
+ {
+ // Resize the hash table if necessary.
+ if (4 * this->size_ / 3 >= this->capacity_)
+ this->expand();
+
+ T** slot = this->find_slot(symbol);
+ if (*slot == NULL)
+ {
+ ++this->size_;
+ *slot = symbol;
+ }
+
+ return *slot;
+ }
+
+ // Return the current size.
+ size_t
+ size() const
+ { return this->size_; }
+
+ // Return the current capacity.
+ size_t
+ capacity() const
+ { return this->capacity_; }
+
+ // Return the contents of slot N.
+ T*
+ operator[](size_t n)
+ { return this->hashtab_[n]; }
+
+ private:
+ // Find a symbol in the hash table, or return an empty slot if
+ // the symbol is not in the table.
+ T**
+ find_slot(T* symbol)
+ {
+ unsigned int index = symbol->hash() & (this->capacity_ - 1);
+ unsigned int step = ((symbol->hash() * 17) & (this->capacity_ - 1)) | 1;
+
+ for (;;)
+ {
+ if (this->hashtab_[index] == NULL
+ || this->hashtab_[index]->equal(symbol))
+ return &this->hashtab_[index];
+ index = (index + step) & (this->capacity_ - 1);
+ }
+ }
+
+ // Expand the hash table.
+ void
+ expand()
+ {
+ if (this->capacity_ == 0)
+ {
+ // Allocate the hash table for the first time.
+ this->capacity_ = Gdb_hashtab::initial_size;
+ this->hashtab_ = new T*[this->capacity_];
+ memset(this->hashtab_, 0, this->capacity_ * sizeof(T*));
+ }
+ else
+ {
+ // Expand and rehash.
+ unsigned int old_cap = this->capacity_;
+ T** old_hashtab = this->hashtab_;
+ this->capacity_ *= 2;
+ this->hashtab_ = new T*[this->capacity_];
+ memset(this->hashtab_, 0, this->capacity_ * sizeof(T*));
+ for (size_t i = 0; i < old_cap; ++i)
+ {
+ if (old_hashtab[i] != NULL)
+ {
+ T** slot = this->find_slot(old_hashtab[i]);
+ *slot = old_hashtab[i];
+ }
+ }
+ delete[] old_hashtab;
+ }
+ }
+
+ // Initial size of the hash table; must be a power of 2.
+ static const int initial_size = 1024;
+ size_t size_;
+ size_t capacity_;
+ T** hashtab_;
+};
+
+// The hash function for strings in the mapped index. This is copied
+// directly from gdb/dwarf2read.c.
+
+static unsigned int
+mapped_index_string_hash(const unsigned char* str)
+{
+ unsigned int r = 0;
+ unsigned char c;
+
+ while ((c = *str++) != 0)
+ {
+ if (gdb_index_version >= 5)
+ c = tolower (c);
+ r = r * 67 + c - 113;
+ }
+
+ return r;
+}
+
+// A specialization of Dwarf_info_reader, for building the .gdb_index.
+
+class Gdb_index_info_reader : public Dwarf_info_reader
+{
+ public:
+ Gdb_index_info_reader(bool is_type_unit,
+ Relobj* object,
+ const unsigned char* symbols,
+ off_t symbols_size,
+ unsigned int shndx,
+ unsigned int reloc_shndx,
+ unsigned int reloc_type,
+ Gdb_index* gdb_index)
+ : Dwarf_info_reader(is_type_unit, object, symbols, symbols_size, shndx,
+ reloc_shndx, reloc_type),
+ gdb_index_(gdb_index), cu_index_(0), cu_language_(0)
+ { }
+
+ ~Gdb_index_info_reader()
+ { this->clear_declarations(); }
+
+ // Print usage statistics.
+ static void
+ print_stats();
+
+ protected:
+ // Visit a compilation unit.
+ virtual void
+ visit_compilation_unit(off_t cu_offset, off_t cu_length, Dwarf_die*);
+
+ // Visit a type unit.
+ virtual void
+ visit_type_unit(off_t tu_offset, off_t type_offset, uint64_t signature,
+ Dwarf_die*);
+
+ private:
+ // A map for recording DIEs we've seen that may be referred to be
+ // later DIEs (via DW_AT_specification or DW_AT_abstract_origin).
+ // The map is indexed by a DIE offset within the compile unit.
+ // PARENT_OFFSET_ is the offset of the DIE that represents the
+ // outer context, and NAME_ is a pointer to a component of the
+ // fully-qualified name.
+ // Normally, the names we point to are in a string table, so we don't
+ // have to manage them, but when we have a fully-qualified name
+ // computed, we put it in the table, and set PARENT_OFFSET_ to -1
+ // indicate a string that we are managing.
+ struct Declaration_pair
+ {
+ Declaration_pair(off_t parent_offset, const char* name)
+ : parent_offset_(parent_offset), name_(name)
+ { }
+
+ off_t parent_offset_;
+ const char* name_;
+ };
+ typedef Unordered_map<off_t, Declaration_pair> Declaration_map;
+
+ // Visit a top-level DIE.
+ void
+ visit_top_die(Dwarf_die* die);
+
+ // Visit the children of a DIE.
+ void
+ visit_children(Dwarf_die* die, Dwarf_die* context);
+
+ // Visit a DIE.
+ void
+ visit_die(Dwarf_die* die, Dwarf_die* context);
+
+ // Visit the children of a DIE.
+ void
+ visit_children_for_decls(Dwarf_die* die);
+
+ // Visit a DIE.
+ void
+ visit_die_for_decls(Dwarf_die* die, Dwarf_die* context);
+
+ // Guess a fully-qualified name for a class type, based on member function
+ // linkage names.
+ std::string
+ guess_full_class_name(Dwarf_die* die);
+
+ // Add a declaration DIE to the table of declarations.
+ void
+ add_declaration(Dwarf_die* die, Dwarf_die* context);
+
+ // Add a declaration whose fully-qualified name is already known.
+ void
+ add_declaration_with_full_name(Dwarf_die* die, const char* full_name);
+
+ // Return the context for a DIE whose parent is at DIE_OFFSET.
+ std::string
+ get_context(off_t die_offset);
+
+ // Construct a fully-qualified name for DIE.
+ std::string
+ get_qualified_name(Dwarf_die* die, Dwarf_die* context);
+
+ // Record the address ranges for a compilation unit.
+ void
+ record_cu_ranges(Dwarf_die* die);
+
+ // Read the .debug_pubnames and .debug_pubtypes tables.
+ bool
+ read_pubnames_and_pubtypes(Dwarf_die* die);
+
+ // Clear the declarations map.
+ void
+ clear_declarations();
+
+ // The Gdb_index section.
+ Gdb_index* gdb_index_;
+ // The current CU index (negative for a TU).
+ int cu_index_;
+ // The language of the current CU or TU.
+ unsigned int cu_language_;
+ // Map from DIE offset to (parent offset, name) pair,
+ // for DW_AT_specification.
+ Declaration_map declarations_;
+
+ // Statistics.
+ // Total number of DWARF compilation units processed.
+ static unsigned int dwarf_cu_count;
+ // Number of DWARF compilation units with pubnames/pubtypes.
+ static unsigned int dwarf_cu_nopubnames_count;
+ // Total number of DWARF type units processed.
+ static unsigned int dwarf_tu_count;
+ // Number of DWARF type units with pubnames/pubtypes.
+ static unsigned int dwarf_tu_nopubnames_count;
+};
+
+// Total number of DWARF compilation units processed.
+unsigned int Gdb_index_info_reader::dwarf_cu_count = 0;
+// Number of DWARF compilation units without pubnames/pubtypes.
+unsigned int Gdb_index_info_reader::dwarf_cu_nopubnames_count = 0;
+// Total number of DWARF type units processed.
+unsigned int Gdb_index_info_reader::dwarf_tu_count = 0;
+// Number of DWARF type units without pubnames/pubtypes.
+unsigned int Gdb_index_info_reader::dwarf_tu_nopubnames_count = 0;
+
+// Process a compilation unit and parse its child DIE.
+
+void
+Gdb_index_info_reader::visit_compilation_unit(off_t cu_offset, off_t cu_length,
+ Dwarf_die* root_die)
+{
+ ++Gdb_index_info_reader::dwarf_cu_count;
+ this->cu_index_ = this->gdb_index_->add_comp_unit(cu_offset, cu_length);
+ this->visit_top_die(root_die);
+}
+
+// Process a type unit and parse its child DIE.
+
+void
+Gdb_index_info_reader::visit_type_unit(off_t tu_offset, off_t type_offset,
+ uint64_t signature, Dwarf_die* root_die)
+{
+ ++Gdb_index_info_reader::dwarf_tu_count;
+ // Use a negative index to flag this as a TU instead of a CU.
+ this->cu_index_ = -1 - this->gdb_index_->add_type_unit(tu_offset, type_offset,
+ signature);
+ this->visit_top_die(root_die);
+}
+
+// Process a top-level DIE.
+// For compile_unit DIEs, record the address ranges. For all
+// interesting tags, add qualified names to the symbol table
+// and process interesting children. We may need to process
+// certain children just for saving declarations that might be
+// referenced by later DIEs with a DW_AT_specification attribute.
+
+void
+Gdb_index_info_reader::visit_top_die(Dwarf_die* die)
+{
+ this->clear_declarations();
+
+ switch (die->tag())
+ {
+ case elfcpp::DW_TAG_compile_unit:
+ case elfcpp::DW_TAG_type_unit:
+ this->cu_language_ = die->int_attribute(elfcpp::DW_AT_language);
+ // Check for languages that require specialized knowledge to
+ // construct fully-qualified names, that we don't yet support.
+ if (this->cu_language_ == elfcpp::DW_LANG_Ada83
+ || this->cu_language_ == elfcpp::DW_LANG_Fortran77
+ || this->cu_language_ == elfcpp::DW_LANG_Fortran90
+ || this->cu_language_ == elfcpp::DW_LANG_Java
+ || this->cu_language_ == elfcpp::DW_LANG_Ada95
+ || this->cu_language_ == elfcpp::DW_LANG_Fortran95)
+ {
+ gold_warning(_("%s: --gdb-index currently supports "
+ "only C and C++ languages"),
+ this->object()->name().c_str());
+ return;
+ }
+ if (die->tag() == elfcpp::DW_TAG_compile_unit)
+ this->record_cu_ranges(die);
+ // If there is a pubnames and/or pubtypes section for this
+ // compilation unit, use those; otherwise, parse the DWARF
+ // info to extract the names.
+ if (!this->read_pubnames_and_pubtypes(die))
+ {
+ if (die->tag() == elfcpp::DW_TAG_compile_unit)
+ ++Gdb_index_info_reader::dwarf_cu_nopubnames_count;
+ else
+ ++Gdb_index_info_reader::dwarf_tu_nopubnames_count;
+ this->visit_children(die, NULL);
+ }
+ break;
+ default:
+ // The top level DIE should be one of the above.
+ gold_warning(_("%s: top level DIE is not DW_TAG_compile_unit "
+ "or DW_TAG_type_unit"),
+ this->object()->name().c_str());
+ return;
+ }
+
+}
+
+// Visit the children of PARENT, looking for symbols to add to the index.
+// CONTEXT points to the DIE to use for constructing the qualified name --
+// NULL if PARENT is the top-level DIE; otherwise it is the same as PARENT.
+
+void
+Gdb_index_info_reader::visit_children(Dwarf_die* parent, Dwarf_die* context)
+{
+ off_t next_offset = 0;
+ for (off_t die_offset = parent->child_offset();
+ die_offset != 0;
+ die_offset = next_offset)
+ {
+ Dwarf_die die(this, die_offset, parent);
+ if (die.tag() == 0)
+ break;
+ this->visit_die(&die, context);
+ next_offset = die.sibling_offset();
+ }
+}
+
+// Visit a child DIE, looking for symbols to add to the index.
+// CONTEXT is the parent DIE, used for constructing the qualified name;
+// it is NULL if the parent DIE is the top-level DIE.
+
+void
+Gdb_index_info_reader::visit_die(Dwarf_die* die, Dwarf_die* context)
+{
+ switch (die->tag())
+ {
+ case elfcpp::DW_TAG_subprogram:
+ case elfcpp::DW_TAG_constant:
+ case elfcpp::DW_TAG_variable:
+ case elfcpp::DW_TAG_enumerator:
+ case elfcpp::DW_TAG_base_type:
+ if (die->is_declaration())
+ this->add_declaration(die, context);
+ else
+ {
+ // If the DIE is not a declaration, add it to the index.
+ std::string full_name = this->get_qualified_name(die, context);
+ if (!full_name.empty())
+ this->gdb_index_->add_symbol(this->cu_index_, full_name.c_str());
+ }
+ break;
+ case elfcpp::DW_TAG_typedef:
+ case elfcpp::DW_TAG_union_type:
+ case elfcpp::DW_TAG_class_type:
+ case elfcpp::DW_TAG_interface_type:
+ case elfcpp::DW_TAG_structure_type:
+ case elfcpp::DW_TAG_enumeration_type:
+ case elfcpp::DW_TAG_subrange_type:
+ case elfcpp::DW_TAG_namespace:
+ {
+ std::string full_name;
+
+ // For classes at the top level, we need to look for a
+ // member function with a linkage name in order to get
+ // the properly-canonicalized name.
+ if (context == NULL
+ && (die->tag() == elfcpp::DW_TAG_class_type
+ || die->tag() == elfcpp::DW_TAG_structure_type
+ || die->tag() == elfcpp::DW_TAG_union_type))
+ full_name.assign(this->guess_full_class_name(die));
+
+ // Because we will visit the children, we need to add this DIE
+ // to the declarations table.
+ if (full_name.empty())
+ this->add_declaration(die, context);
+ else
+ this->add_declaration_with_full_name(die, full_name.c_str());
+
+ // If the DIE is not a declaration, add it to the index.
+ // Gdb stores a namespace in the index even when it is
+ // a declaration.
+ if (die->tag() == elfcpp::DW_TAG_namespace
+ || !die->is_declaration())
+ {
+ if (full_name.empty())
+ full_name = this->get_qualified_name(die, context);
+ if (!full_name.empty())
+ this->gdb_index_->add_symbol(this->cu_index_,
+ full_name.c_str());
+ }
+
+ // We're interested in the children only for namespaces and
+ // enumeration types. For enumeration types, we do not include
+ // the enumeration tag as part of the full name. For other tags,
+ // visit the children only to collect declarations.
+ if (die->tag() == elfcpp::DW_TAG_namespace
+ || die->tag() == elfcpp::DW_TAG_enumeration_type)
+ this->visit_children(die, die);
+ else
+ this->visit_children_for_decls(die);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+// Visit the children of PARENT, looking only for declarations that
+// may be referenced by later specification DIEs.
+
+void
+Gdb_index_info_reader::visit_children_for_decls(Dwarf_die* parent)
+{
+ off_t next_offset = 0;
+ for (off_t die_offset = parent->child_offset();
+ die_offset != 0;
+ die_offset = next_offset)
+ {
+ Dwarf_die die(this, die_offset, parent);
+ if (die.tag() == 0)
+ break;
+ this->visit_die_for_decls(&die, parent);
+ next_offset = die.sibling_offset();
+ }
+}
+
+// Visit a child DIE, looking only for declarations that
+// may be referenced by later specification DIEs.
+
+void
+Gdb_index_info_reader::visit_die_for_decls(Dwarf_die* die, Dwarf_die* context)
+{
+ switch (die->tag())
+ {
+ case elfcpp::DW_TAG_subprogram:
+ case elfcpp::DW_TAG_constant:
+ case elfcpp::DW_TAG_variable:
+ case elfcpp::DW_TAG_enumerator:
+ case elfcpp::DW_TAG_base_type:
+ {
+ if (die->is_declaration())
+ this->add_declaration(die, context);
+ }
+ break;
+ case elfcpp::DW_TAG_typedef:
+ case elfcpp::DW_TAG_union_type:
+ case elfcpp::DW_TAG_class_type:
+ case elfcpp::DW_TAG_interface_type:
+ case elfcpp::DW_TAG_structure_type:
+ case elfcpp::DW_TAG_enumeration_type:
+ case elfcpp::DW_TAG_subrange_type:
+ case elfcpp::DW_TAG_namespace:
+ {
+ if (die->is_declaration())
+ this->add_declaration(die, context);
+ this->visit_children_for_decls(die);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+// Extract the class name from the linkage name of a member function.
+// This code is adapted from ../gdb/cp-support.c.
+
+#define d_left(dc) (dc)->u.s_binary.left
+#define d_right(dc) (dc)->u.s_binary.right
+
+static char*
+class_name_from_linkage_name(const char* linkage_name)
+{
+ void* storage;
+ struct demangle_component* tree =
+ cplus_demangle_v3_components(linkage_name, DMGL_NO_OPTS, &storage);
+ if (tree == NULL)
+ return NULL;
+
+ int done = 0;
+
+ // First strip off any qualifiers, if we have a function or
+ // method.
+ while (!done)
+ switch (tree->type)
+ {
+ case DEMANGLE_COMPONENT_CONST:
+ case DEMANGLE_COMPONENT_RESTRICT:
+ case DEMANGLE_COMPONENT_VOLATILE:
+ case DEMANGLE_COMPONENT_CONST_THIS:
+ case DEMANGLE_COMPONENT_RESTRICT_THIS:
+ case DEMANGLE_COMPONENT_VOLATILE_THIS:
+ case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+ tree = d_left(tree);
+ break;
+ default:
+ done = 1;
+ break;
+ }
+
+ // If what we have now is a function, discard the argument list.
+ if (tree->type == DEMANGLE_COMPONENT_TYPED_NAME)
+ tree = d_left(tree);
+
+ // If what we have now is a template, strip off the template
+ // arguments. The left subtree may be a qualified name.
+ if (tree->type == DEMANGLE_COMPONENT_TEMPLATE)
+ tree = d_left(tree);
+
+ // What we have now should be a name, possibly qualified.
+ // Additional qualifiers could live in the left subtree or the right
+ // subtree. Find the last piece.
+ done = 0;
+ struct demangle_component* prev_comp = NULL;
+ struct demangle_component* cur_comp = tree;
+ while (!done)
+ switch (cur_comp->type)
+ {
+ case DEMANGLE_COMPONENT_QUAL_NAME:
+ case DEMANGLE_COMPONENT_LOCAL_NAME:
+ prev_comp = cur_comp;
+ cur_comp = d_right(cur_comp);
+ break;
+ case DEMANGLE_COMPONENT_TEMPLATE:
+ case DEMANGLE_COMPONENT_NAME:
+ case DEMANGLE_COMPONENT_CTOR:
+ case DEMANGLE_COMPONENT_DTOR:
+ case DEMANGLE_COMPONENT_OPERATOR:
+ case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
+ done = 1;
+ break;
+ default:
+ done = 1;
+ cur_comp = NULL;
+ break;
+ }
+
+ char* ret = NULL;
+ if (cur_comp != NULL && prev_comp != NULL)
+ {
+ // We want to discard the rightmost child of PREV_COMP.
+ *prev_comp = *d_left(prev_comp);
+ size_t allocated_size;
+ ret = cplus_demangle_print(DMGL_NO_OPTS, tree, 30, &allocated_size);
+ }
+
+ free(storage);
+ return ret;
+}
+
+// Guess a fully-qualified name for a class type, based on member function
+// linkage names. This is needed for class/struct/union types at the
+// top level, because GCC does not always properly embed them within
+// the namespace. As in gdb, we look for a member function with a linkage
+// name and extract the qualified name from the demangled name.
+
+std::string
+Gdb_index_info_reader::guess_full_class_name(Dwarf_die* die)
+{
+ std::string full_name;
+ off_t next_offset = 0;
+
+ // This routine scans ahead in the DIE structure, possibly advancing
+ // the relocation tracker beyond the current DIE. We need to checkpoint
+ // the tracker and reset it when we're done.
+ uint64_t checkpoint = this->get_reloc_checkpoint();
+
+ for (off_t child_offset = die->child_offset();
+ child_offset != 0;
+ child_offset = next_offset)
+ {
+ Dwarf_die child(this, child_offset, die);
+ if (child.tag() == 0)
+ break;
+ if (child.tag() == elfcpp::DW_TAG_subprogram)
+ {
+ const char* linkage_name = child.linkage_name();
+ if (linkage_name != NULL)
+ {
+ char* guess = class_name_from_linkage_name(linkage_name);
+ if (guess != NULL)
+ {
+ full_name.assign(guess);
+ free(guess);
+ break;
+ }
+ }
+ }
+ next_offset = child.sibling_offset();
+ }
+
+ this->reset_relocs(checkpoint);
+ return full_name;
+}
+
+// Add a declaration DIE to the table of declarations.
+
+void
+Gdb_index_info_reader::add_declaration(Dwarf_die* die, Dwarf_die* context)
+{
+ const char* name = die->name();
+
+ off_t parent_offset = context != NULL ? context->offset() : 0;
+
+ // If this DIE has a DW_AT_specification or DW_AT_abstract_origin
+ // attribute, use the parent and name from the earlier declaration.
+ off_t spec = die->specification();
+ if (spec == 0)
+ spec = die->abstract_origin();
+ if (spec > 0)
+ {
+ Declaration_map::iterator it = this->declarations_.find(spec);
+ if (it != this->declarations_.end())
+ {
+ parent_offset = it->second.parent_offset_;
+ name = it->second.name_;
+ }
+ }
+
+ if (name == NULL)
+ {
+ if (die->tag() == elfcpp::DW_TAG_namespace)
+ name = "(anonymous namespace)";
+ else if (die->tag() == elfcpp::DW_TAG_union_type)
+ name = "(anonymous union)";
+ else
+ name = "(unknown)";
+ }
+
+ Declaration_pair decl(parent_offset, name);
+ this->declarations_.insert(std::make_pair(die->offset(), decl));
+}
+
+// Add a declaration whose fully-qualified name is already known.
+// In the case where we had to get the canonical name by demangling
+// a linkage name, this ensures we use that name instead of the one
+// provided in DW_AT_name.
+
+void
+Gdb_index_info_reader::add_declaration_with_full_name(
+ Dwarf_die* die,
+ const char* full_name)
+{
+ // We need to copy the name.
+ int len = strlen(full_name);
+ char* copy = new char[len + 1];
+ memcpy(copy, full_name, len + 1);
+
+ // Flag that we now manage the memory this points to.
+ Declaration_pair decl(-1, copy);
+ this->declarations_.insert(std::make_pair(die->offset(), decl));
+}
+
+// Return the context for a DIE whose parent is at DIE_OFFSET.
+
+std::string
+Gdb_index_info_reader::get_context(off_t die_offset)
+{
+ std::string context;
+ Declaration_map::iterator it = this->declarations_.find(die_offset);
+ if (it != this->declarations_.end())
+ {
+ off_t parent_offset = it->second.parent_offset_;
+ if (parent_offset > 0)
+ {
+ context = get_context(parent_offset);
+ context.append("::");
+ }
+ if (it->second.name_ != NULL)
+ context.append(it->second.name_);
+ }
+ return context;
+}
+
+// Construct the fully-qualified name for DIE.
+
+std::string
+Gdb_index_info_reader::get_qualified_name(Dwarf_die* die, Dwarf_die* context)
+{
+ std::string full_name;
+ const char* name = die->name();
+
+ off_t parent_offset = context != NULL ? context->offset() : 0;
+
+ // If this DIE has a DW_AT_specification or DW_AT_abstract_origin
+ // attribute, use the parent and name from the earlier declaration.
+ off_t spec = die->specification();
+ if (spec == 0)
+ spec = die->abstract_origin();
+ if (spec > 0)
+ {
+ Declaration_map::iterator it = this->declarations_.find(spec);
+ if (it != this->declarations_.end())
+ {
+ parent_offset = it->second.parent_offset_;
+ name = it->second.name_;
+ }
+ }
+
+ if (name == NULL && die->tag() == elfcpp::DW_TAG_namespace)
+ name = "(anonymous namespace)";
+ else if (name == NULL)
+ return full_name;
+
+ // If this is an enumerator constant, skip the immediate parent,
+ // which is the enumeration tag.
+ if (die->tag() == elfcpp::DW_TAG_enumerator)
+ {
+ Declaration_map::iterator it = this->declarations_.find(parent_offset);
+ if (it != this->declarations_.end())
+ parent_offset = it->second.parent_offset_;
+ }
+
+ if (parent_offset > 0)
+ {
+ full_name.assign(this->get_context(parent_offset));
+ full_name.append("::");
+ }
+ full_name.append(name);
+
+ return full_name;
+}
+
+// Record the address ranges for a compilation unit.
+
+void
+Gdb_index_info_reader::record_cu_ranges(Dwarf_die* die)
+{
+ unsigned int shndx;
+ unsigned int shndx2;
+
+ off_t ranges_offset = die->ref_attribute(elfcpp::DW_AT_ranges, &shndx);
+ if (ranges_offset != -1)
+ {
+ Dwarf_range_list* ranges = this->read_range_list(shndx, ranges_offset);
+ if (ranges != NULL)
+ this->gdb_index_->add_address_range_list(this->object(),
+ this->cu_index_, ranges);
+ return;
+ }
+
+ off_t low_pc = die->address_attribute(elfcpp::DW_AT_low_pc, &shndx);
+ off_t high_pc = die->address_attribute(elfcpp::DW_AT_high_pc, &shndx2);
+ if (high_pc == -1)
+ {
+ high_pc = die->uint_attribute(elfcpp::DW_AT_high_pc);
+ high_pc += low_pc;
+ shndx2 = shndx;
+ }
+ if ((low_pc != 0 || high_pc != 0) && low_pc != -1)
+ {
+ if (shndx != shndx2)
+ {
+ gold_warning(_("%s: DWARF info may be corrupt; low_pc and high_pc "
+ "are in different sections"),
+ this->object()->name().c_str());
+ return;
+ }
+ if (shndx == 0 || this->object()->is_section_included(shndx))
+ {
+ Dwarf_range_list* ranges = new Dwarf_range_list();
+ ranges->add(shndx, low_pc, high_pc);
+ this->gdb_index_->add_address_range_list(this->object(),
+ this->cu_index_, ranges);
+ }
+ }
+}
+
+// Read the .debug_pubnames and .debug_pubtypes tables for the CU or TU.
+// Returns TRUE if either a pubnames or pubtypes section was found.
+
+bool
+Gdb_index_info_reader::read_pubnames_and_pubtypes(Dwarf_die* die)
+{
+ bool ret = false;
+
+ // If we find a DW_AT_GNU_pubnames attribute, read the pubnames table.
+ unsigned int pubnames_shndx;
+ off_t pubnames_offset = die->ref_attribute(elfcpp::DW_AT_GNU_pubnames,
+ &pubnames_shndx);
+ if (pubnames_offset != -1)
+ {
+ if (this->gdb_index_->pubnames_read(pubnames_shndx, pubnames_offset))
+ ret = true;
+ else
+ {
+ Dwarf_pubnames_table pubnames(false);
+ if (!pubnames.read_section(this->object(), pubnames_shndx))
+ return false;
+ if (!pubnames.read_header(pubnames_offset))
+ return false;
+ while (true)
+ {
+ const char* name = pubnames.next_name();
+ if (name == NULL)
+ break;
+ this->gdb_index_->add_symbol(this->cu_index_, name);
+ }
+ ret = true;
+ }
+ }
+
+ // If we find a DW_AT_GNU_pubtypes attribute, read the pubtypes table.
+ unsigned int pubtypes_shndx;
+ off_t pubtypes_offset = die->ref_attribute(elfcpp::DW_AT_GNU_pubtypes,
+ &pubtypes_shndx);
+ if (pubtypes_offset != -1)
+ {
+ if (this->gdb_index_->pubtypes_read(pubtypes_shndx, pubtypes_offset))
+ ret = true;
+ else
+ {
+ Dwarf_pubnames_table pubtypes(true);
+ if (!pubtypes.read_section(this->object(), pubtypes_shndx))
+ return false;
+ if (!pubtypes.read_header(pubtypes_offset))
+ return false;
+ while (true)
+ {
+ const char* name = pubtypes.next_name();
+ if (name == NULL)
+ break;
+ this->gdb_index_->add_symbol(this->cu_index_, name);
+ }
+ ret = true;
+ }
+ }
+
+ return ret;
+}
+
+// Clear the declarations map.
+void
+Gdb_index_info_reader::clear_declarations()
+{
+ // Free strings in memory we manage.
+ for (Declaration_map::iterator it = this->declarations_.begin();
+ it != this->declarations_.end();
+ ++it)
+ {
+ if (it->second.parent_offset_ == -1)
+ delete[] it->second.name_;
+ }
+
+ this->declarations_.clear();
+}
+
+// Print usage statistics.
+void
+Gdb_index_info_reader::print_stats()
+{
+ fprintf(stderr, _("%s: DWARF CUs: %u\n"),
+ program_name, Gdb_index_info_reader::dwarf_cu_count);
+ fprintf(stderr, _("%s: DWARF CUs without pubnames/pubtypes: %u\n"),
+ program_name, Gdb_index_info_reader::dwarf_cu_nopubnames_count);
+ fprintf(stderr, _("%s: DWARF TUs: %u\n"),
+ program_name, Gdb_index_info_reader::dwarf_tu_count);
+ fprintf(stderr, _("%s: DWARF TUs without pubnames/pubtypes: %u\n"),
+ program_name, Gdb_index_info_reader::dwarf_tu_nopubnames_count);
+}
+
+// Class Gdb_index.
+
+// Construct the .gdb_index section.
+
+Gdb_index::Gdb_index(Output_section* gdb_index_section)
+ : Output_section_data(4),
+ gdb_index_section_(gdb_index_section),
+ comp_units_(),
+ type_units_(),
+ ranges_(),
+ cu_vector_list_(),
+ cu_vector_offsets_(NULL),
+ stringpool_(),
+ tu_offset_(0),
+ addr_offset_(0),
+ symtab_offset_(0),
+ cu_pool_offset_(0),
+ stringpool_offset_(0),
+ pubnames_shndx_(0),
+ pubnames_offset_(0),
+ pubtypes_shndx_(0),
+ pubtypes_offset_(0)
+{
+ this->gdb_symtab_ = new Gdb_hashtab<Gdb_symbol>();
+}
+
+Gdb_index::~Gdb_index()
+{
+ // Free the memory used by the symbol table.
+ delete this->gdb_symtab_;
+ // Free the memory used by the CU vectors.
+ for (unsigned int i = 0; i < this->cu_vector_list_.size(); ++i)
+ delete this->cu_vector_list_[i];
+}
+
+// Scan a .debug_info or .debug_types input section.
+
+void
+Gdb_index::scan_debug_info(bool is_type_unit,
+ Relobj* object,
+ const unsigned char* symbols,
+ off_t symbols_size,
+ unsigned int shndx,
+ unsigned int reloc_shndx,
+ unsigned int reloc_type)
+{
+ Gdb_index_info_reader dwinfo(is_type_unit, object,
+ symbols, symbols_size,
+ shndx, reloc_shndx,
+ reloc_type, this);
+ dwinfo.parse();
+}
+
+// Add a symbol.
+
+void
+Gdb_index::add_symbol(int cu_index, const char* sym_name)
+{
+ unsigned int hash = mapped_index_string_hash(
+ reinterpret_cast<const unsigned char*>(sym_name));
+ Gdb_symbol* sym = new Gdb_symbol();
+ this->stringpool_.add(sym_name, true, &sym->name_key);
+ sym->hashval = hash;
+ sym->cu_vector_index = 0;
+
+ Gdb_symbol* found = this->gdb_symtab_->add(sym);
+ if (found == sym)
+ {
+ // New symbol -- allocate a new CU index vector.
+ found->cu_vector_index = this->cu_vector_list_.size();
+ this->cu_vector_list_.push_back(new Cu_vector());
+ }
+ else
+ {
+ // Found an existing symbol -- append to the existing
+ // CU index vector.
+ delete sym;
+ }
+
+ // Add the CU index to the vector list for this symbol,
+ // if it's not already on the list. We only need to
+ // check the last added entry.
+ Cu_vector* cu_vec = this->cu_vector_list_[found->cu_vector_index];
+ if (cu_vec->size() == 0 || cu_vec->back() != cu_index)
+ cu_vec->push_back(cu_index);
+}
+
+// Return TRUE if we have already processed the pubnames set at
+// OFFSET in section SHNDX
+
+bool
+Gdb_index::pubnames_read(unsigned int shndx, off_t offset)
+{
+ bool ret = (this->pubnames_shndx_ == shndx
+ && this->pubnames_offset_ == offset);
+ this->pubnames_shndx_ = shndx;
+ this->pubnames_offset_ = offset;
+ return ret;
+}
+
+// Return TRUE if we have already processed the pubtypes set at
+// OFFSET in section SHNDX
+
+bool
+Gdb_index::pubtypes_read(unsigned int shndx, off_t offset)
+{
+ bool ret = (this->pubtypes_shndx_ == shndx
+ && this->pubtypes_offset_ == offset);
+ this->pubtypes_shndx_ = shndx;
+ this->pubtypes_offset_ = offset;
+ return ret;
+}
+
+// Set the size of the .gdb_index section.
+
+void
+Gdb_index::set_final_data_size()
+{
+ // Finalize the string pool.
+ this->stringpool_.set_string_offsets();
+
+ // Compute the total size of the CU vectors.
+ // For each CU vector, include one entry for the count at the
+ // beginning of the vector.
+ unsigned int cu_vector_count = this->cu_vector_list_.size();
+ unsigned int cu_vector_size = 0;
+ this->cu_vector_offsets_ = new off_t[cu_vector_count];
+ for (unsigned int i = 0; i < cu_vector_count; ++i)
+ {
+ Cu_vector* cu_vec = this->cu_vector_list_[i];
+ cu_vector_offsets_[i] = cu_vector_size;
+ cu_vector_size += gdb_index_offset_size * (cu_vec->size() + 1);
+ }
+
+ // Assign relative offsets to each portion of the index,
+ // and find the total size of the section.
+ section_size_type data_size = gdb_index_hdr_size;
+ data_size += this->comp_units_.size() * gdb_index_cu_size;
+ this->tu_offset_ = data_size;
+ data_size += this->type_units_.size() * gdb_index_tu_size;
+ this->addr_offset_ = data_size;
+ for (unsigned int i = 0; i < this->ranges_.size(); ++i)
+ data_size += this->ranges_[i].ranges->size() * gdb_index_addr_size;
+ this->symtab_offset_ = data_size;
+ data_size += this->gdb_symtab_->capacity() * gdb_index_sym_size;
+ this->cu_pool_offset_ = data_size;
+ data_size += cu_vector_size;
+ this->stringpool_offset_ = data_size;
+ data_size += this->stringpool_.get_strtab_size();
+
+ this->set_data_size(data_size);
+}
+
+// Write the data to the file.
+
+void
+Gdb_index::do_write(Output_file* of)
+{
+ const off_t off = this->offset();
+ const off_t oview_size = this->data_size();
+ unsigned char* const oview = of->get_output_view(off, oview_size);
+ unsigned char* pov = oview;
+
+ // Write the file header.
+ // (1) Version number.
+ elfcpp::Swap<32, false>::writeval(pov, gdb_index_version);
+ pov += 4;
+ // (2) Offset of the CU list.
+ elfcpp::Swap<32, false>::writeval(pov, gdb_index_hdr_size);
+ pov += 4;
+ // (3) Offset of the types CU list.
+ elfcpp::Swap<32, false>::writeval(pov, this->tu_offset_);
+ pov += 4;
+ // (4) Offset of the address area.
+ elfcpp::Swap<32, false>::writeval(pov, this->addr_offset_);
+ pov += 4;
+ // (5) Offset of the symbol table.
+ elfcpp::Swap<32, false>::writeval(pov, this->symtab_offset_);
+ pov += 4;
+ // (6) Offset of the constant pool.
+ elfcpp::Swap<32, false>::writeval(pov, this->cu_pool_offset_);
+ pov += 4;
+
+ gold_assert(pov - oview == gdb_index_hdr_size);
+
+ // Write the CU list.
+ unsigned int comp_units_count = this->comp_units_.size();
+ for (unsigned int i = 0; i < comp_units_count; ++i)
+ {
+ const Comp_unit& cu = this->comp_units_[i];
+ elfcpp::Swap<64, false>::writeval(pov, cu.cu_offset);
+ elfcpp::Swap<64, false>::writeval(pov + 8, cu.cu_length);
+ pov += 16;
+ }
+
+ gold_assert(pov - oview == this->tu_offset_);
+
+ // Write the types CU list.
+ for (unsigned int i = 0; i < this->type_units_.size(); ++i)
+ {
+ const Type_unit& tu = this->type_units_[i];
+ elfcpp::Swap<64, false>::writeval(pov, tu.tu_offset);
+ elfcpp::Swap<64, false>::writeval(pov + 8, tu.type_offset);
+ elfcpp::Swap<64, false>::writeval(pov + 16, tu.type_signature);
+ pov += 24;
+ }
+
+ gold_assert(pov - oview == this->addr_offset_);
+
+ // Write the address area.
+ for (unsigned int i = 0; i < this->ranges_.size(); ++i)
+ {
+ int cu_index = this->ranges_[i].cu_index;
+ // Translate negative indexes, which refer to a TU, to a
+ // logical index into a concatenated CU/TU list.
+ if (cu_index < 0)
+ cu_index = comp_units_count + (-1 - cu_index);
+ Relobj* object = this->ranges_[i].object;
+ const Dwarf_range_list& ranges = *this->ranges_[i].ranges;
+ for (unsigned int j = 0; j < ranges.size(); ++j)
+ {
+ const Dwarf_range_list::Range& range = ranges[j];
+ uint64_t base = 0;
+ if (range.shndx > 0)
+ {
+ const Output_section* os = object->output_section(range.shndx);
+ base = (os->address()
+ + object->output_section_offset(range.shndx));
+ }
+ elfcpp::Swap_aligned32<64, false>::writeval(pov, base + range.start);
+ elfcpp::Swap_aligned32<64, false>::writeval(pov + 8,
+ base + range.end);
+ elfcpp::Swap<32, false>::writeval(pov + 16, cu_index);
+ pov += 20;
+ }
+ }
+
+ gold_assert(pov - oview == this->symtab_offset_);
+
+ // Write the symbol table.
+ for (unsigned int i = 0; i < this->gdb_symtab_->capacity(); ++i)
+ {
+ const Gdb_symbol* sym = (*this->gdb_symtab_)[i];
+ section_offset_type name_offset = 0;
+ unsigned int cu_vector_offset = 0;
+ if (sym != NULL)
+ {
+ name_offset = (this->stringpool_.get_offset_from_key(sym->name_key)
+ + this->stringpool_offset_ - this->cu_pool_offset_);
+ cu_vector_offset = this->cu_vector_offsets_[sym->cu_vector_index];
+ }
+ elfcpp::Swap<32, false>::writeval(pov, name_offset);
+ elfcpp::Swap<32, false>::writeval(pov + 4, cu_vector_offset);
+ pov += 8;
+ }
+
+ gold_assert(pov - oview == this->cu_pool_offset_);
+
+ // Write the CU vectors into the constant pool.
+ for (unsigned int i = 0; i < this->cu_vector_list_.size(); ++i)
+ {
+ Cu_vector* cu_vec = this->cu_vector_list_[i];
+ elfcpp::Swap<32, false>::writeval(pov, cu_vec->size());
+ pov += 4;
+ for (unsigned int j = 0; j < cu_vec->size(); ++j)
+ {
+ int cu_index = (*cu_vec)[j];
+ if (cu_index < 0)
+ cu_index = comp_units_count + (-1 - cu_index);
+ elfcpp::Swap<32, false>::writeval(pov, cu_index);
+ pov += 4;
+ }
+ }
+
+ gold_assert(pov - oview == this->stringpool_offset_);
+
+ // Write the strings into the constant pool.
+ this->stringpool_.write_to_buffer(pov, oview_size - this->stringpool_offset_);
+
+ of->write_output_view(off, oview_size, oview);
+}
+
+// Print usage statistics.
+void
+Gdb_index::print_stats()
+{
+ if (parameters->options().gdb_index())
+ Gdb_index_info_reader::print_stats();
+}
+
+} // End namespace gold.
diff --git a/binutils-2.22/gold/gdb-index.h b/binutils-2.22/gold/gdb-index.h
new file mode 100644
index 0000000..1ca38cc
--- /dev/null
+++ b/binutils-2.22/gold/gdb-index.h
@@ -0,0 +1,213 @@
+// gdb-index.h -- generate .gdb_index section for fast debug lookup -*- C++ -*-
+
+// Copyright 2012 Free Software Foundation, Inc.
+// Written by Cary Coutant <ccoutant@google.com>.
+
+// This file is part of gold.
+
+// 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.
+
+#include <sys/types.h>
+#include <vector>
+
+#include "gold.h"
+#include "output.h"
+#include "mapfile.h"
+#include "stringpool.h"
+
+#ifndef GOLD_GDB_INDEX_H
+#define GOLD_GDB_INDEX_H
+
+namespace gold
+{
+
+class Output_section;
+class Output_file;
+class Mapfile;
+template<int size, bool big_endian>
+class Sized_relobj;
+class Dwarf_range_list;
+template <typename T>
+class Gdb_hashtab;
+
+// This class manages the .gdb_index section, which is a fast
+// lookup table for DWARF information used by the gdb debugger.
+// The format of this section is described in gdb/doc/gdb.texinfo.
+
+class Gdb_index : public Output_section_data
+{
+ public:
+ Gdb_index(Output_section* gdb_index_section);
+
+ ~Gdb_index();
+
+ // Scan a .debug_info or .debug_types input section.
+ void scan_debug_info(bool is_type_unit,
+ Relobj* object,
+ const unsigned char* symbols,
+ off_t symbols_size,
+ unsigned int shndx,
+ unsigned int reloc_shndx,
+ unsigned int reloc_type);
+
+ // Add a compilation unit.
+ int
+ add_comp_unit(off_t cu_offset, off_t cu_length)
+ {
+ this->comp_units_.push_back(Comp_unit(cu_offset, cu_length));
+ return this->comp_units_.size() - 1;
+ }
+
+ // Add a type unit.
+ int
+ add_type_unit(off_t tu_offset, off_t type_offset, uint64_t signature)
+ {
+ this->type_units_.push_back(Type_unit(tu_offset, type_offset, signature));
+ return this->type_units_.size() - 1;
+ }
+
+ // Add an address range.
+ void
+ add_address_range_list(Relobj* object, unsigned int cu_index,
+ Dwarf_range_list* ranges)
+ {
+ this->ranges_.push_back(Per_cu_range_list(object, cu_index, ranges));
+ }
+
+ // Add a symbol.
+ void
+ add_symbol(int cu_index, const char* sym_name);
+
+ // Return TRUE if we have already processed the pubnames set at
+ // OFFSET in section SHNDX
+ bool
+ pubnames_read(unsigned int shndx, off_t offset);
+
+ // Return TRUE if we have already processed the pubtypes set at
+ // OFFSET in section SHNDX
+ bool
+ pubtypes_read(unsigned int shndx, off_t offset);
+
+ // Print usage statistics.
+ static void
+ print_stats();
+
+ protected:
+ // This is called to update the section size prior to assigning
+ // the address and file offset.
+ void
+ update_data_size()
+ { this->set_final_data_size(); }
+
+ // Set the final data size.
+ void
+ set_final_data_size();
+
+ // Write the data to the file.
+ void
+ do_write(Output_file*);
+
+ // Write to a map file.
+ void
+ do_print_to_mapfile(Mapfile* mapfile) const
+ { mapfile->print_output_data(this, _("** gdb_index")); }
+
+ private:
+ // An entry in the compilation unit list.
+ struct Comp_unit
+ {
+ Comp_unit(off_t off, off_t len)
+ : cu_offset(off), cu_length(len)
+ { }
+ uint64_t cu_offset;
+ uint64_t cu_length;
+ };
+
+ // An entry in the type unit list.
+ struct Type_unit
+ {
+ Type_unit(off_t off, off_t toff, uint64_t sig)
+ : tu_offset(off), type_offset(toff), type_signature(sig)
+ { }
+ uint64_t tu_offset;
+ uint64_t type_offset;
+ uint64_t type_signature;
+ };
+
+ // An entry in the address range list.
+ struct Per_cu_range_list
+ {
+ Per_cu_range_list(Relobj* obj, uint32_t index, Dwarf_range_list* r)
+ : object(obj), cu_index(index), ranges(r)
+ { }
+ Relobj* object;
+ uint32_t cu_index;
+ Dwarf_range_list* ranges;
+ };
+
+ // A symbol table entry.
+ struct Gdb_symbol
+ {
+ Stringpool::Key name_key;
+ unsigned int hashval;
+ unsigned int cu_vector_index;
+
+ // Return the hash value.
+ unsigned int
+ hash()
+ { return this->hashval; }
+
+ // Return true if this symbol is the same as SYMBOL.
+ bool
+ equal(Gdb_symbol* symbol)
+ { return this->name_key == symbol->name_key; }
+ };
+
+ typedef std::vector<int> Cu_vector;
+
+ // The .gdb_index section.
+ Output_section* gdb_index_section_;
+ // The list of DWARF compilation units.
+ std::vector<Comp_unit> comp_units_;
+ // The list of DWARF type units.
+ std::vector<Type_unit> type_units_;
+ // The list of address ranges.
+ std::vector<Per_cu_range_list> ranges_;
+ // The symbol table.
+ Gdb_hashtab<Gdb_symbol>* gdb_symtab_;
+ // The CU vector portion of the constant pool.
+ std::vector<Cu_vector*> cu_vector_list_;
+ // An array to map from a CU vector index to an offset to the constant pool.
+ off_t* cu_vector_offsets_;
+ // The string portion of the constant pool.
+ Stringpool stringpool_;
+ // Offsets of the various pieces of the .gdb_index section.
+ off_t tu_offset_;
+ off_t addr_offset_;
+ off_t symtab_offset_;
+ off_t cu_pool_offset_;
+ off_t stringpool_offset_;
+ // Section index and offset of last read pubnames section.
+ unsigned int pubnames_shndx_;
+ off_t pubnames_offset_;
+ // Section index and offset of last read pubtypes section.
+ unsigned int pubtypes_shndx_;
+ off_t pubtypes_offset_;
+};
+
+} // End namespace gold.
+
+#endif // !defined(GOLD_GDB_INDEX_H)
diff --git a/binutils-2.22/gold/gold.cc b/binutils-2.22/gold/gold.cc
index f2d73fe..dddf5ad 100644
--- a/binutils-2.22/gold/gold.cc
+++ b/binutils-2.22/gold/gold.cc
@@ -1,6 +1,7 @@
// gold.cc -- main linker functions
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -45,6 +46,7 @@
#include "gc.h"
#include "icf.h"
#include "incremental.h"
+#include "timer.h"
namespace gold
{
@@ -135,7 +137,7 @@ Middle_runner::run(Workqueue* workqueue, const Task* task)
// This class arranges the tasks to process the relocs for garbage collection.
-class Gc_runner : public Task_function_runner
+class Gc_runner : public Task_function_runner
{
public:
Gc_runner(const General_options& options,
@@ -160,9 +162,9 @@ class Gc_runner : public Task_function_runner
void
Gc_runner::run(Workqueue* workqueue, const Task* task)
{
- queue_middle_gc_tasks(this->options_, task, this->input_objects_,
- this->symtab_, this->layout_, workqueue,
- this->mapfile_);
+ queue_middle_gc_tasks(this->options_, task, this->input_objects_,
+ this->symtab_, this->layout_, workqueue,
+ this->mapfile_);
}
// Queue up the initial set of tasks for this link job.
@@ -197,46 +199,29 @@ queue_initial_tasks(const General_options& options,
// For incremental links, the base output file.
Incremental_binary* ibase = NULL;
- if (parameters->incremental())
- {
- if (options.relocatable())
- gold_error(_("incremental linking is incompatible with -r"));
- if (options.emit_relocs())
- gold_error(_("incremental linking is incompatible with --emit-relocs"));
- if (options.gc_sections())
- gold_error(_("incremental linking is incompatible with --gc-sections"));
- if (options.icf_enabled())
- gold_error(_("incremental linking is incompatible with --icf"));
- if (options.has_plugins())
- gold_error(_("incremental linking is incompatible with --plugin"));
- if (strcmp(options.compress_debug_sections(), "none") != 0)
- gold_error(_("incremental linking is incompatible with "
- "--compress-debug-sections"));
-
- if (parameters->incremental_update())
+ if (parameters->incremental_update())
+ {
+ Output_file* of = new Output_file(options.output_file_name());
+ if (of->open_base_file(options.incremental_base(), true))
{
- Output_file* of = new Output_file(options.output_file_name());
- if (of->open_base_file(options.incremental_base(), true))
- {
- ibase = open_incremental_binary(of);
- if (ibase != NULL
- && ibase->check_inputs(cmdline, layout->incremental_inputs()))
- ibase->init_layout(layout);
- else
- {
- delete ibase;
- ibase = NULL;
- of->close();
- }
- }
- if (ibase == NULL)
+ ibase = open_incremental_binary(of);
+ if (ibase != NULL
+ && ibase->check_inputs(cmdline, layout->incremental_inputs()))
+ ibase->init_layout(layout);
+ else
{
- if (set_parameters_incremental_full())
- gold_info(_("linking with --incremental-full"));
- else
- gold_fallback(_("restart link with --incremental-full"));
+ delete ibase;
+ ibase = NULL;
+ of->close();
}
}
+ if (ibase == NULL)
+ {
+ if (set_parameters_incremental_full())
+ gold_info(_("linking with --incremental-full"));
+ else
+ gold_fallback(_("restart link with --incremental-full"));
+ }
}
// Read the input files. We have to add the symbols to the symbol
@@ -303,21 +288,21 @@ queue_initial_tasks(const General_options& options,
{
workqueue->queue(new Task_function(new Gc_runner(options,
input_objects,
- symtab,
- layout,
- mapfile),
- this_blocker,
- "Task_function Gc_runner"));
+ symtab,
+ layout,
+ mapfile),
+ this_blocker,
+ "Task_function Gc_runner"));
}
else
{
workqueue->queue(new Task_function(new Middle_runner(options,
- input_objects,
- symtab,
- layout,
- mapfile),
- this_blocker,
- "Task_function Middle_runner"));
+ input_objects,
+ symtab,
+ layout,
+ mapfile),
+ this_blocker,
+ "Task_function Middle_runner"));
}
}
@@ -483,12 +468,12 @@ queue_middle_gc_tasks(const General_options& options,
}
workqueue->queue(new Task_function(new Middle_runner(options,
- input_objects,
- symtab,
- layout,
- mapfile),
- this_blocker,
- "Task_function Middle_runner"));
+ input_objects,
+ symtab,
+ layout,
+ mapfile),
+ this_blocker,
+ "Task_function Middle_runner"));
}
// Queue up the middle set of tasks. These are the tasks which run
@@ -504,26 +489,30 @@ queue_middle_tasks(const General_options& options,
Workqueue* workqueue,
Mapfile* mapfile)
{
+ Timer* timer = parameters->timer();
+ if (timer != NULL)
+ timer->stamp(0);
+
// Add any symbols named with -u options to the symbol table.
symtab->add_undefined_symbols_from_command_line(layout);
// If garbage collection was chosen, relocs have been read and processed
- // at this point by pre_middle_tasks. Layout can then be done for all
+ // at this point by pre_middle_tasks. Layout can then be done for all
// objects.
if (parameters->options().gc_sections())
{
// Find the start symbol if any.
Symbol* start_sym = symtab->lookup(parameters->entry());
if (start_sym != NULL)
- {
- bool is_ordinary;
- unsigned int shndx = start_sym->shndx(&is_ordinary);
- if (is_ordinary)
- {
- symtab->gc()->worklist().push(
- Section_id(start_sym->object(), shndx));
- }
- }
+ {
+ bool is_ordinary;
+ unsigned int shndx = start_sym->shndx(&is_ordinary);
+ if (is_ordinary)
+ {
+ symtab->gc()->worklist().push(
+ Section_id(start_sym->object(), shndx));
+ }
+ }
// Symbols named with -u should not be considered garbage.
symtab->gc_mark_undef_symbols(layout);
gold_assert(symtab->gc() != NULL);
@@ -531,29 +520,29 @@ queue_middle_tasks(const General_options& options,
symtab->gc()->do_transitive_closure();
}
- // If identical code folding (--icf) is chosen it makes sense to do it
- // only after garbage collection (--gc-sections) as we do not want to
+ // If identical code folding (--icf) is chosen it makes sense to do it
+ // only after garbage collection (--gc-sections) as we do not want to
// be folding sections that will be garbage.
if (parameters->options().icf_enabled())
{
symtab->icf()->find_identical_sections(input_objects, symtab);
}
- // Call Object::layout for the second time to determine the
- // output_sections for all referenced input sections. When
- // --gc-sections or --icf is turned on, Object::layout is
- // called twice. It is called the first time when the
+ // Call Object::layout for the second time to determine the
+ // output_sections for all referenced input sections. When
+ // --gc-sections or --icf is turned on, Object::layout is
+ // called twice. It is called the first time when the
// symbols are added.
if (parameters->options().gc_sections()
|| parameters->options().icf_enabled())
{
for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
- p != input_objects->relobj_end();
- ++p)
- {
- Task_lock_obj<Object> tlo(task, *p);
- (*p)->layout(symtab, layout, NULL);
- }
+ p != input_objects->relobj_end();
+ ++p)
+ {
+ Task_lock_obj<Object> tlo(task, *p);
+ (*p)->layout(symtab, layout, NULL);
+ }
}
// Layout deferred objects due to plugins.
@@ -562,26 +551,40 @@ queue_middle_tasks(const General_options& options,
Plugin_manager* plugins = parameters->options().plugins();
gold_assert(plugins != NULL);
plugins->layout_deferred_objects();
- }
+ }
+
+ /* If plugins have specified a section order, re-arrange input sections
+ according to a specified section order. If --section-ordering-file is
+ also specified, do not do anything here. */
+ if (parameters->options().has_plugins()
+ && layout->is_section_ordering_specified()
+ && !parameters->options().section_ordering_file ())
+ {
+ for (Layout::Section_list::const_iterator p
+ = layout->section_list().begin();
+ p != layout->section_list().end();
+ ++p)
+ (*p)->update_section_layout(layout->get_section_order_map());
+ }
if (parameters->options().gc_sections()
|| parameters->options().icf_enabled())
{
for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
- p != input_objects->relobj_end();
- ++p)
- {
- // Update the value of output_section stored in rd.
- Read_relocs_data* rd = (*p)->get_relocs_data();
- for (Read_relocs_data::Relocs_list::iterator q = rd->relocs.begin();
- q != rd->relocs.end();
- ++q)
- {
- q->output_section = (*p)->output_section(q->data_shndx);
- q->needs_special_offset_handling =
- (*p)->is_output_section_offset_invalid(q->data_shndx);
- }
- }
+ p != input_objects->relobj_end();
+ ++p)
+ {
+ // Update the value of output_section stored in rd.
+ Read_relocs_data* rd = (*p)->get_relocs_data();
+ for (Read_relocs_data::Relocs_list::iterator q = rd->relocs.begin();
+ q != rd->relocs.end();
+ ++q)
+ {
+ q->output_section = (*p)->output_section(q->data_shndx);
+ q->needs_special_offset_handling =
+ (*p)->is_output_section_offset_invalid(q->data_shndx);
+ }
+ }
}
// We have to support the case of not seeing any input objects, and
@@ -678,7 +681,7 @@ queue_middle_tasks(const General_options& options,
Target* target = const_cast<Target*>(&parameters->target());
// Attach sections to segments.
- layout->attach_sections_to_segments();
+ layout->attach_sections_to_segments(target);
if (!parameters->options().relocatable())
{
@@ -715,12 +718,12 @@ queue_middle_tasks(const General_options& options,
|| parameters->options().icf_enabled())
{
for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
- p != input_objects->relobj_end();
- ++p)
+ p != input_objects->relobj_end();
+ ++p)
{
Task_token* next_blocker = new Task_token(true);
next_blocker->add_blocker();
- workqueue->queue(new Scan_relocs(symtab, layout, *p,
+ workqueue->queue(new Scan_relocs(symtab, layout, *p,
(*p)->get_relocs_data(),
this_blocker, next_blocker));
this_blocker = next_blocker;
@@ -740,15 +743,15 @@ queue_middle_tasks(const General_options& options,
// some of the sections, and thus change our minds about the types
// of references made to the symbols.
for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
- p != input_objects->relobj_end();
- ++p)
- {
+ p != input_objects->relobj_end();
+ ++p)
+ {
Task_token* next_blocker = new Task_token(true);
next_blocker->add_blocker();
- workqueue->queue(new Read_relocs(symtab, layout, *p, this_blocker,
+ workqueue->queue(new Read_relocs(symtab, layout, *p, this_blocker,
next_blocker));
this_blocker = next_blocker;
- }
+ }
}
if (this_blocker == NULL)
@@ -760,7 +763,7 @@ queue_middle_tasks(const General_options& options,
// blocker here so that we can run the layout task immediately.
this_blocker = new Task_token(true);
}
- else
+ else
{
// If we failed to open any input files, it's possible for
// THIS_BLOCKER to be NULL here. There's no real point in
@@ -775,7 +778,7 @@ queue_middle_tasks(const General_options& options,
workqueue->queue(new Task_function(new Layout_task_runner(options,
input_objects,
symtab,
- target,
+ target,
layout,
mapfile),
this_blocker,
@@ -793,6 +796,10 @@ queue_final_tasks(const General_options& options,
Workqueue* workqueue,
Output_file* of)
{
+ Timer* timer = parameters->timer();
+ if (timer != NULL)
+ timer->stamp(1);
+
int thread_count = options.thread_count_final();
if (thread_count == 0)
thread_count = std::max(2, input_objects->number_of_input_objects());
diff --git a/binutils-2.22/gold/gold.h b/binutils-2.22/gold/gold.h
index 4258d55..9aa7cf3 100644
--- a/binutils-2.22/gold/gold.h
+++ b/binutils-2.22/gold/gold.h
@@ -80,6 +80,22 @@
#define reserve_unordered_map(map, n) ((map)->rehash(n))
+#ifndef HAVE_TR1_HASH_OFF_T
+// The library does not support hashes of off_t values. Add support
+// here. This is likely to be specific to libstdc++. This issue
+// arises with GCC 4.1.x when compiling in 32-bit mode with a 64-bit
+// off_t type.
+namespace std { namespace tr1 {
+template<>
+struct hash<off_t> : public std::unary_function<off_t, std::size_t>
+{
+ std::size_t
+ operator()(off_t val) const
+ { return static_cast<std::size_t>(val); }
+};
+} } // Close namespaces.
+#endif // !defined(HAVE_TR1_HASH_OFF_T)
+
#elif defined(HAVE_EXT_HASH_MAP) && defined(HAVE_EXT_HASH_SET)
#include <ext/hash_map>
diff --git a/binutils-2.22/gold/i386.cc b/binutils-2.22/gold/i386.cc
index 205653e..47f33a0 100644
--- a/binutils-2.22/gold/i386.cc
+++ b/binutils-2.22/gold/i386.cc
@@ -1,6 +1,7 @@
// i386.cc -- i386 target support for gold.
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -39,6 +40,7 @@
#include "target-select.h"
#include "tls.h"
#include "freebsd.h"
+#include "nacl.h"
#include "gc.h"
namespace
@@ -47,13 +49,17 @@ namespace
using namespace gold;
// A class to handle the PLT data.
+// This is an abstract base class that handles most of the linker details
+// but does not know the actual contents of PLT entries. The derived
+// classes below fill in those details.
class Output_data_plt_i386 : public Output_section_data
{
public:
typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, false> Reloc_section;
- Output_data_plt_i386(Layout*, Output_data_space*, Output_data_space*);
+ Output_data_plt_i386(Layout*, uint64_t addralign,
+ Output_data_space*, Output_data_space*);
// Add an entry to the PLT.
void
@@ -89,14 +95,14 @@ class Output_data_plt_i386 : public Output_section_data
{ return this->count_ + this->irelative_count_; }
// Return the offset of the first non-reserved PLT entry.
- static unsigned int
+ unsigned int
first_plt_entry_offset()
- { return plt_entry_size; }
+ { return this->get_plt_entry_size(); }
// Return the size of a PLT entry.
- static unsigned int
- get_plt_entry_size()
- { return plt_entry_size; }
+ unsigned int
+ get_plt_entry_size() const
+ { return this->do_get_plt_entry_size(); }
// Return the PLT address to use for a global symbol.
uint64_t
@@ -106,43 +112,73 @@ class Output_data_plt_i386 : public Output_section_data
uint64_t
address_for_local(const Relobj*, unsigned int symndx);
- protected:
+ // Add .eh_frame information for the PLT.
void
- do_adjust_output_section(Output_section* os);
+ add_eh_frame(Layout* layout)
+ { this->do_add_eh_frame(layout); }
- // Write to a map file.
+ protected:
+ // Fill the first PLT entry, given the pointer to the PLT section data
+ // and the runtime address of the GOT.
void
- do_print_to_mapfile(Mapfile* mapfile) const
- { mapfile->print_output_data(this, _("** PLT")); }
+ fill_first_plt_entry(unsigned char* pov,
+ elfcpp::Elf_types<32>::Elf_Addr got_address)
+ { this->do_fill_first_plt_entry(pov, got_address); }
+
+ // Fill a normal PLT entry, given the pointer to the entry's data in the
+ // section, the runtime address of the GOT, the offset into the GOT of
+ // the corresponding slot, the offset into the relocation section of the
+ // corresponding reloc, and the offset of this entry within the whole
+ // PLT. Return the offset from this PLT entry's runtime address that
+ // should be used to compute the initial value of the GOT slot.
+ unsigned int
+ fill_plt_entry(unsigned char* pov,
+ elfcpp::Elf_types<32>::Elf_Addr got_address,
+ unsigned int got_offset,
+ unsigned int plt_offset,
+ unsigned int plt_rel_offset)
+ {
+ return this->do_fill_plt_entry(pov, got_address, got_offset,
+ plt_offset, plt_rel_offset);
+ }
- private:
- // The size of an entry in the PLT.
- static const int plt_entry_size = 16;
+ virtual unsigned int
+ do_get_plt_entry_size() const = 0;
- // The first entry in the PLT for an executable.
- static const unsigned char exec_first_plt_entry[plt_entry_size];
+ virtual void
+ do_fill_first_plt_entry(unsigned char* pov,
+ elfcpp::Elf_types<32>::Elf_Addr got_address) = 0;
- // The first entry in the PLT for a shared object.
- static const unsigned char dyn_first_plt_entry[plt_entry_size];
+ virtual unsigned int
+ do_fill_plt_entry(unsigned char* pov,
+ elfcpp::Elf_types<32>::Elf_Addr got_address,
+ unsigned int got_offset,
+ unsigned int plt_offset,
+ unsigned int plt_rel_offset) = 0;
- // Other entries in the PLT for an executable.
- static const unsigned char exec_plt_entry[plt_entry_size];
+ virtual void
+ do_add_eh_frame(Layout*) = 0;
- // Other entries in the PLT for a shared object.
- static const unsigned char dyn_plt_entry[plt_entry_size];
+ void
+ do_adjust_output_section(Output_section* os);
+
+ // Write to a map file.
+ void
+ do_print_to_mapfile(Mapfile* mapfile) const
+ { mapfile->print_output_data(this, _("** PLT")); }
// The .eh_frame unwind information for the PLT.
+ // The CIE is common across variants of the PLT format.
static const int plt_eh_frame_cie_size = 16;
- static const int plt_eh_frame_fde_size = 32;
static const unsigned char plt_eh_frame_cie[plt_eh_frame_cie_size];
- static const unsigned char plt_eh_frame_fde[plt_eh_frame_fde_size];
+ private:
// Set the final size.
void
set_final_data_size()
{
this->set_data_size((this->count_ + this->irelative_count_ + 1)
- * plt_entry_size);
+ * this->get_plt_entry_size());
}
// Write out the PLT data.
@@ -192,6 +228,101 @@ class Output_data_plt_i386 : public Output_section_data
std::vector<Local_ifunc> local_ifuncs_;
};
+// This is an abstract class for the standard PLT layout.
+// The derived classes below handle the actual PLT contents
+// for the executable (non-PIC) and shared-library (PIC) cases.
+// The unwind information is uniform across those two, so it's here.
+
+class Output_data_plt_i386_standard : public Output_data_plt_i386
+{
+ public:
+ Output_data_plt_i386_standard(Layout* layout,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative)
+ : Output_data_plt_i386(layout, plt_entry_size, got_plt, got_irelative)
+ { }
+
+ protected:
+ virtual unsigned int
+ do_get_plt_entry_size() const
+ { return plt_entry_size; }
+
+ virtual void
+ do_add_eh_frame(Layout* layout)
+ {
+ layout->add_eh_frame_for_plt(this, plt_eh_frame_cie, plt_eh_frame_cie_size,
+ plt_eh_frame_fde, plt_eh_frame_fde_size);
+ }
+
+ // The size of an entry in the PLT.
+ static const int plt_entry_size = 16;
+
+ // The .eh_frame unwind information for the PLT.
+ static const int plt_eh_frame_fde_size = 32;
+ static const unsigned char plt_eh_frame_fde[plt_eh_frame_fde_size];
+};
+
+// Actually fill the PLT contents for an executable (non-PIC).
+
+class Output_data_plt_i386_exec : public Output_data_plt_i386_standard
+{
+public:
+ Output_data_plt_i386_exec(Layout* layout,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative)
+ : Output_data_plt_i386_standard(layout, got_plt, got_irelative)
+ { }
+
+ protected:
+ virtual void
+ do_fill_first_plt_entry(unsigned char* pov,
+ elfcpp::Elf_types<32>::Elf_Addr got_address);
+
+ virtual unsigned int
+ do_fill_plt_entry(unsigned char* pov,
+ elfcpp::Elf_types<32>::Elf_Addr got_address,
+ unsigned int got_offset,
+ unsigned int plt_offset,
+ unsigned int plt_rel_offset);
+
+ private:
+ // The first entry in the PLT for an executable.
+ static const unsigned char first_plt_entry[plt_entry_size];
+
+ // Other entries in the PLT for an executable.
+ static const unsigned char plt_entry[plt_entry_size];
+};
+
+// Actually fill the PLT contents for a shared library (PIC).
+
+class Output_data_plt_i386_dyn : public Output_data_plt_i386_standard
+{
+ public:
+ Output_data_plt_i386_dyn(Layout* layout,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative)
+ : Output_data_plt_i386_standard(layout, got_plt, got_irelative)
+ { }
+
+ protected:
+ virtual void
+ do_fill_first_plt_entry(unsigned char* pov, elfcpp::Elf_types<32>::Elf_Addr);
+
+ virtual unsigned int
+ do_fill_plt_entry(unsigned char* pov,
+ elfcpp::Elf_types<32>::Elf_Addr,
+ unsigned int got_offset,
+ unsigned int plt_offset,
+ unsigned int plt_rel_offset);
+
+ private:
+ // The first entry in the PLT for a shared object.
+ static const unsigned char first_plt_entry[plt_entry_size];
+
+ // Other entries in the PLT for a shared object.
+ static const unsigned char plt_entry[plt_entry_size];
+};
+
// The i386 target class.
// TLS info comes from
// http://people.redhat.com/drepper/tls.pdf
@@ -202,28 +333,28 @@ class Target_i386 : public Sized_target<32, false>
public:
typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, false> Reloc_section;
- Target_i386()
- : Sized_target<32, false>(&i386_info),
+ Target_i386(const Target::Target_info* info = &i386_info)
+ : Sized_target<32, false>(info),
got_(NULL), plt_(NULL), got_plt_(NULL), got_irelative_(NULL),
got_tlsdesc_(NULL), global_offset_table_(NULL), rel_dyn_(NULL),
rel_irelative_(NULL), copy_relocs_(elfcpp::R_386_COPY), dynbss_(NULL),
got_mod_index_offset_(-1U), tls_base_symbol_defined_(false)
{ }
- // Process the relocations to determine unreferenced sections for
+ // Process the relocations to determine unreferenced sections for
// garbage collection.
void
gc_process_relocs(Symbol_table* symtab,
- Layout* layout,
- Sized_relobj_file<32, false>* object,
- unsigned int data_shndx,
- unsigned int sh_type,
- const unsigned char* prelocs,
- size_t reloc_count,
- Output_section* output_section,
- bool needs_special_offset_handling,
- size_t local_symbol_count,
- const unsigned char* plocal_symbols);
+ Layout* layout,
+ Sized_relobj_file<32, false>* object,
+ unsigned int data_shndx,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ size_t local_symbol_count,
+ const unsigned char* plocal_symbols);
// Scan the relocations to look for symbol adjustments.
void
@@ -371,6 +502,28 @@ class Target_i386 : public Sized_target<32, false>
unsigned int
plt_entry_size() const;
+ protected:
+ // Instantiate the plt_ member.
+ // This chooses the right PLT flavor for an executable or a shared object.
+ Output_data_plt_i386*
+ make_data_plt(Layout* layout,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative,
+ bool dyn)
+ { return this->do_make_data_plt(layout, got_plt, got_irelative, dyn); }
+
+ virtual Output_data_plt_i386*
+ do_make_data_plt(Layout* layout,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative,
+ bool dyn)
+ {
+ if (dyn)
+ return new Output_data_plt_i386_dyn(layout, got_plt, got_irelative);
+ else
+ return new Output_data_plt_i386_exec(layout, got_plt, got_irelative);
+ }
+
private:
// The class which scans relocations.
struct Scan
@@ -397,23 +550,23 @@ class Target_i386 : public Sized_target<32, false>
inline bool
local_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout,
- Target_i386* target,
- Sized_relobj_file<32, false>* object,
- unsigned int data_shndx,
- Output_section* output_section,
- const elfcpp::Rel<32, false>& reloc,
+ Target_i386* target,
+ Sized_relobj_file<32, false>* object,
+ unsigned int data_shndx,
+ Output_section* output_section,
+ const elfcpp::Rel<32, false>& reloc,
unsigned int r_type,
- const elfcpp::Sym<32, false>& lsym);
+ const elfcpp::Sym<32, false>& lsym);
inline bool
global_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout,
Target_i386* target,
- Sized_relobj_file<32, false>* object,
- unsigned int data_shndx,
- Output_section* output_section,
+ Sized_relobj_file<32, false>* object,
+ unsigned int data_shndx,
+ Output_section* output_section,
const elfcpp::Rel<32, false>& reloc,
unsigned int r_type,
- Symbol* gsym);
+ Symbol* gsym);
inline bool
possible_function_pointer_reloc(unsigned int r_type);
@@ -451,8 +604,8 @@ class Target_i386 : public Sized_target<32, false>
// Return whether the static relocation needs to be applied.
inline bool
should_apply_static_reloc(const Sized_symbol<32>* gsym,
- unsigned int r_type,
- bool is_32bit,
+ unsigned int r_type,
+ bool is_32bit,
Output_section* output_section);
// Do a relocation. Return false if the caller should not issue
@@ -469,7 +622,7 @@ class Target_i386 : public Sized_target<32, false>
// Do a TLS relocation.
inline void
relocate_tls(const Relocate_info<32, false>*, Target_i386* target,
- size_t relnum, const elfcpp::Rel<32, false>&,
+ size_t relnum, const elfcpp::Rel<32, false>&,
unsigned int r_type, const Sized_symbol<32>*,
const Symbol_value<32>*,
unsigned char*, elfcpp::Elf_types<32>::Elf_Addr,
@@ -628,7 +781,7 @@ class Target_i386 : public Sized_target<32, false>
// Add a potential copy relocation.
void
copy_reloc(Symbol_table* symtab, Layout* layout,
- Sized_relobj_file<32, false>* object,
+ Sized_relobj_file<32, false>* object,
unsigned int shndx, Output_section* output_section,
Symbol* sym, const elfcpp::Rel<32, false>& reloc)
{
@@ -696,6 +849,8 @@ const Target::Target_info Target_i386::i386_info =
0x08048000, // default_text_segment_address
0x1000, // abi_pagesize (overridable by -z max-page-size)
0x1000, // common_pagesize (overridable by -z common-page-size)
+ false, // isolate_execinstr
+ 0, // rosegment_gap
elfcpp::SHN_UNDEF, // small_common_shndx
elfcpp::SHN_UNDEF, // large_common_shndx
0, // small_common_section_flags
@@ -823,9 +978,11 @@ Target_i386::rel_irelative_section(Layout* layout)
// section just for PLT entries.
Output_data_plt_i386::Output_data_plt_i386(Layout* layout,
+ uint64_t addralign,
Output_data_space* got_plt,
Output_data_space* got_irelative)
- : Output_section_data(16), layout_(layout), tls_desc_rel_(NULL),
+ : Output_section_data(addralign),
+ layout_(layout), tls_desc_rel_(NULL),
irelative_rel_(NULL), got_plt_(got_plt), got_irelative_(got_irelative),
count_(0), irelative_count_(0), global_ifuncs_(), local_ifuncs_()
{
@@ -833,11 +990,6 @@ Output_data_plt_i386::Output_data_plt_i386(Layout* layout,
layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
elfcpp::SHF_ALLOC, this->rel_,
ORDER_DYNAMIC_PLT_RELOCS, false);
-
- // Add unwind information if requested.
- if (parameters->options().ld_generated_unwind_info())
- layout->add_eh_frame_for_plt(this, plt_eh_frame_cie, plt_eh_frame_cie_size,
- plt_eh_frame_fde, plt_eh_frame_fde_size);
}
void
@@ -860,7 +1012,7 @@ Output_data_plt_i386::add_entry(Symbol_table* symtab, Layout* layout,
if (gsym->type() == elfcpp::STT_GNU_IFUNC
&& gsym->can_use_relative_reloc(false))
{
- gsym->set_plt_offset(this->irelative_count_ * plt_entry_size);
+ gsym->set_plt_offset(this->irelative_count_ * this->get_plt_entry_size());
++this->irelative_count_;
section_offset_type got_offset =
this->got_irelative_->current_data_size();
@@ -877,7 +1029,7 @@ Output_data_plt_i386::add_entry(Symbol_table* symtab, Layout* layout,
{
// When setting the PLT offset we skip the initial reserved PLT
// entry.
- gsym->set_plt_offset((this->count_ + 1) * plt_entry_size);
+ gsym->set_plt_offset((this->count_ + 1) * this->get_plt_entry_size());
++this->count_;
@@ -908,7 +1060,7 @@ Output_data_plt_i386::add_local_ifunc_entry(
Sized_relobj_file<32, false>* relobj,
unsigned int local_sym_index)
{
- unsigned int plt_offset = this->irelative_count_ * plt_entry_size;
+ unsigned int plt_offset = this->irelative_count_ * this->get_plt_entry_size();
++this->irelative_count_;
section_offset_type got_offset = this->got_irelative_->current_data_size();
@@ -997,7 +1149,7 @@ Output_data_plt_i386::address_for_global(const Symbol* gsym)
uint64_t offset = 0;
if (gsym->type() == elfcpp::STT_GNU_IFUNC
&& gsym->can_use_relative_reloc(false))
- offset = (this->count_ + 1) * plt_entry_size;
+ offset = (this->count_ + 1) * this->get_plt_entry_size();
return this->address() + offset;
}
@@ -1007,12 +1159,12 @@ Output_data_plt_i386::address_for_global(const Symbol* gsym)
uint64_t
Output_data_plt_i386::address_for_local(const Relobj*, unsigned int)
{
- return this->address() + (this->count_ + 1) * plt_entry_size;
+ return this->address() + (this->count_ + 1) * this->get_plt_entry_size();
}
// The first entry in the PLT for an executable.
-const unsigned char Output_data_plt_i386::exec_first_plt_entry[plt_entry_size] =
+const unsigned char Output_data_plt_i386_exec::first_plt_entry[plt_entry_size] =
{
0xff, 0x35, // pushl contents of memory address
0, 0, 0, 0, // replaced with address of .got + 4
@@ -1021,18 +1173,36 @@ const unsigned char Output_data_plt_i386::exec_first_plt_entry[plt_entry_size] =
0, 0, 0, 0 // unused
};
+void
+Output_data_plt_i386_exec::do_fill_first_plt_entry(
+ unsigned char* pov,
+ elfcpp::Elf_types<32>::Elf_Addr got_address)
+{
+ memcpy(pov, first_plt_entry, plt_entry_size);
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_address + 4);
+ elfcpp::Swap<32, false>::writeval(pov + 8, got_address + 8);
+}
+
// The first entry in the PLT for a shared object.
-const unsigned char Output_data_plt_i386::dyn_first_plt_entry[plt_entry_size] =
+const unsigned char Output_data_plt_i386_dyn::first_plt_entry[plt_entry_size] =
{
0xff, 0xb3, 4, 0, 0, 0, // pushl 4(%ebx)
0xff, 0xa3, 8, 0, 0, 0, // jmp *8(%ebx)
0, 0, 0, 0 // unused
};
+void
+Output_data_plt_i386_dyn::do_fill_first_plt_entry(
+ unsigned char* pov,
+ elfcpp::Elf_types<32>::Elf_Addr)
+{
+ memcpy(pov, first_plt_entry, plt_entry_size);
+}
+
// Subsequent entries in the PLT for an executable.
-const unsigned char Output_data_plt_i386::exec_plt_entry[plt_entry_size] =
+const unsigned char Output_data_plt_i386_exec::plt_entry[plt_entry_size] =
{
0xff, 0x25, // jmp indirect
0, 0, 0, 0, // replaced with address of symbol in .got
@@ -1042,9 +1212,25 @@ const unsigned char Output_data_plt_i386::exec_plt_entry[plt_entry_size] =
0, 0, 0, 0 // replaced with offset to start of .plt
};
+unsigned int
+Output_data_plt_i386_exec::do_fill_plt_entry(
+ unsigned char* pov,
+ elfcpp::Elf_types<32>::Elf_Addr got_address,
+ unsigned int got_offset,
+ unsigned int plt_offset,
+ unsigned int plt_rel_offset)
+{
+ memcpy(pov, plt_entry, plt_entry_size);
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
+ got_address + got_offset);
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 7, plt_rel_offset);
+ elfcpp::Swap<32, false>::writeval(pov + 12, - (plt_offset + 12 + 4));
+ return 6;
+}
+
// Subsequent entries in the PLT for a shared object.
-const unsigned char Output_data_plt_i386::dyn_plt_entry[plt_entry_size] =
+const unsigned char Output_data_plt_i386_dyn::plt_entry[plt_entry_size] =
{
0xff, 0xa3, // jmp *offset(%ebx)
0, 0, 0, 0, // replaced with offset of symbol in .got
@@ -1054,6 +1240,20 @@ const unsigned char Output_data_plt_i386::dyn_plt_entry[plt_entry_size] =
0, 0, 0, 0 // replaced with offset to start of .plt
};
+unsigned int
+Output_data_plt_i386_dyn::do_fill_plt_entry(unsigned char* pov,
+ elfcpp::Elf_types<32>::Elf_Addr,
+ unsigned int got_offset,
+ unsigned int plt_offset,
+ unsigned int plt_rel_offset)
+{
+ memcpy(pov, plt_entry, plt_entry_size);
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_offset);
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 7, plt_rel_offset);
+ elfcpp::Swap<32, false>::writeval(pov + 12, - (plt_offset + 12 + 4));
+ return 6;
+}
+
// The .eh_frame unwind information for the PLT.
const unsigned char
@@ -1076,7 +1276,7 @@ Output_data_plt_i386::plt_eh_frame_cie[plt_eh_frame_cie_size] =
};
const unsigned char
-Output_data_plt_i386::plt_eh_frame_fde[plt_eh_frame_fde_size] =
+Output_data_plt_i386_standard::plt_eh_frame_fde[plt_eh_frame_fde_size] =
{
0, 0, 0, 0, // Replaced with offset to .plt.
0, 0, 0, 0, // Replaced with size of .plt.
@@ -1129,15 +1329,8 @@ Output_data_plt_i386::do_write(Output_file* of)
elfcpp::Elf_types<32>::Elf_Addr plt_address = this->address();
elfcpp::Elf_types<32>::Elf_Addr got_address = this->got_plt_->address();
- if (parameters->options().output_is_position_independent())
- memcpy(pov, dyn_first_plt_entry, plt_entry_size);
- else
- {
- memcpy(pov, exec_first_plt_entry, plt_entry_size);
- elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_address + 4);
- elfcpp::Swap<32, false>::writeval(pov + 8, got_address + 8);
- }
- pov += plt_entry_size;
+ this->fill_first_plt_entry(pov, got_address);
+ pov += this->get_plt_entry_size();
unsigned char* got_pov = got_view;
@@ -1154,40 +1347,29 @@ Output_data_plt_i386::do_write(Output_file* of)
const int rel_size = elfcpp::Elf_sizes<32>::rel_size;
- unsigned int plt_offset = plt_entry_size;
+ unsigned int plt_offset = this->get_plt_entry_size();
unsigned int plt_rel_offset = 0;
unsigned int got_offset = 12;
const unsigned int count = this->count_ + this->irelative_count_;
for (unsigned int i = 0;
i < count;
++i,
- pov += plt_entry_size,
+ pov += this->get_plt_entry_size(),
got_pov += 4,
- plt_offset += plt_entry_size,
+ plt_offset += this->get_plt_entry_size(),
plt_rel_offset += rel_size,
got_offset += 4)
{
// Set and adjust the PLT entry itself.
-
- if (parameters->options().output_is_position_independent())
- {
- memcpy(pov, dyn_plt_entry, plt_entry_size);
- elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_offset);
- }
- else
- {
- memcpy(pov, exec_plt_entry, plt_entry_size);
- elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
- (got_address
- + got_offset));
- }
-
- elfcpp::Swap_unaligned<32, false>::writeval(pov + 7, plt_rel_offset);
- elfcpp::Swap<32, false>::writeval(pov + 12,
- - (plt_offset + plt_entry_size));
+ unsigned int lazy_offset = this->fill_plt_entry(pov,
+ got_address,
+ got_offset,
+ plt_offset,
+ plt_rel_offset);
// Set the entry in the GOT.
- elfcpp::Swap<32, false>::writeval(got_pov, plt_address + plt_offset + 6);
+ elfcpp::Swap<32, false>::writeval(got_pov,
+ plt_address + plt_offset + lazy_offset);
}
// If any STT_GNU_IFUNC symbols have PLT entries, we need to change
@@ -1234,8 +1416,16 @@ Target_i386::make_plt_section(Symbol_table* symtab, Layout* layout)
// Create the GOT sections first.
this->got_section(symtab, layout);
- this->plt_ = new Output_data_plt_i386(layout, this->got_plt_,
- this->got_irelative_);
+ const bool dyn = parameters->options().output_is_position_independent();
+ this->plt_ = this->make_data_plt(layout,
+ this->got_plt_,
+ this->got_irelative_,
+ dyn);
+
+ // Add unwind information if requested.
+ if (parameters->options().ld_generated_unwind_info())
+ this->plt_->add_eh_frame(layout);
+
layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR),
@@ -1291,7 +1481,7 @@ Target_i386::plt_entry_count() const
unsigned int
Target_i386::first_plt_entry_offset() const
{
- return Output_data_plt_i386::first_plt_entry_offset();
+ return this->plt_->first_plt_entry_offset();
}
// Return the size of each PLT entry.
@@ -1299,7 +1489,7 @@ Target_i386::first_plt_entry_offset() const
unsigned int
Target_i386::plt_entry_size() const
{
- return Output_data_plt_i386::get_plt_entry_size();
+ return this->plt_->get_plt_entry_size();
}
// Get the section to use for TLS_DESC relocations.
@@ -1340,7 +1530,7 @@ Target_i386::define_tls_base_symbol(Symbol_table* symtab, Layout* layout)
unsigned int
Target_i386::got_mod_index_entry(Symbol_table* symtab, Layout* layout,
- Sized_relobj_file<32, false>* object)
+ Sized_relobj_file<32, false>* object)
{
if (this->got_mod_index_offset_ == -1U)
{
@@ -1349,7 +1539,7 @@ Target_i386::got_mod_index_entry(Symbol_table* symtab, Layout* layout,
Output_data_got<32, false>* got = this->got_section(symtab, layout);
unsigned int got_offset = got->add_constant(0);
rel_dyn->add_local(object, 0, elfcpp::R_386_TLS_DTPMOD32, got,
- got_offset);
+ got_offset);
got->add_constant(0);
this->got_mod_index_offset_ = got_offset;
}
@@ -1504,7 +1694,7 @@ Target_i386::Scan::reloc_needs_plt_for_ifunc(
int flags = Scan::get_reference_flags(r_type);
if (flags & Symbol::TLS_REF)
gold_error(_("%s: unsupported TLS reloc %u for IFUNC symbol"),
- object->name().c_str(), r_type);
+ object->name().c_str(), r_type);
return flags != 0;
}
@@ -1512,14 +1702,14 @@ Target_i386::Scan::reloc_needs_plt_for_ifunc(
inline void
Target_i386::Scan::local(Symbol_table* symtab,
- Layout* layout,
- Target_i386* target,
- Sized_relobj_file<32, false>* object,
- unsigned int data_shndx,
- Output_section* output_section,
- const elfcpp::Rel<32, false>& reloc,
- unsigned int r_type,
- const elfcpp::Sym<32, false>& lsym)
+ Layout* layout,
+ Target_i386* target,
+ Sized_relobj_file<32, false>* object,
+ unsigned int data_shndx,
+ Output_section* output_section,
+ const elfcpp::Rel<32, false>& reloc,
+ unsigned int r_type,
+ const elfcpp::Sym<32, false>& lsym)
{
// A local STT_GNU_IFUNC symbol may require a PLT entry.
if (lsym.get_st_type() == elfcpp::STT_GNU_IFUNC
@@ -1544,13 +1734,13 @@ Target_i386::Scan::local(Symbol_table* symtab,
// an R_386_RELATIVE relocation so the dynamic loader can
// relocate it easily.
if (parameters->options().output_is_position_independent())
- {
- Reloc_section* rel_dyn = target->rel_dyn_section(layout);
- unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+ {
+ Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+ unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
rel_dyn->add_local_relative(object, r_sym, elfcpp::R_386_RELATIVE,
output_section, data_shndx,
reloc.get_r_offset());
- }
+ }
break;
case elfcpp::R_386_16:
@@ -1561,15 +1751,15 @@ Target_i386::Scan::local(Symbol_table* symtab,
// data section, we need to be careful not to apply this
// relocation statically.
if (parameters->options().output_is_position_independent())
- {
- Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+ {
+ Reloc_section* rel_dyn = target->rel_dyn_section(layout);
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
- if (lsym.get_st_type() != elfcpp::STT_SECTION)
+ if (lsym.get_st_type() != elfcpp::STT_SECTION)
rel_dyn->add_local(object, r_sym, r_type, output_section,
data_shndx, reloc.get_r_offset());
- else
- {
- gold_assert(lsym.get_st_value() == 0);
+ else
+ {
+ gold_assert(lsym.get_st_value() == 0);
unsigned int shndx = lsym.get_st_shndx();
bool is_ordinary;
shndx = object->adjust_sym_shndx(r_sym, shndx,
@@ -1581,8 +1771,8 @@ Target_i386::Scan::local(Symbol_table* symtab,
rel_dyn->add_local_section(object, shndx,
r_type, output_section,
data_shndx, reloc.get_r_offset());
- }
- }
+ }
+ }
break;
case elfcpp::R_386_PC32:
@@ -1603,9 +1793,9 @@ Target_i386::Scan::local(Symbol_table* symtab,
case elfcpp::R_386_GOT32:
{
- // The symbol requires a GOT entry.
- Output_data_got<32, false>* got = target->got_section(symtab, layout);
- unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+ // The symbol requires a GOT entry.
+ Output_data_got<32, false>* got = target->got_section(symtab, layout);
+ unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
// For a STT_GNU_IFUNC symbol we want the PLT offset. That
// lets function pointers compare correctly with shared
@@ -1615,20 +1805,20 @@ Target_i386::Scan::local(Symbol_table* symtab,
is_new = got->add_local_plt(object, r_sym, GOT_TYPE_STANDARD);
else
is_new = got->add_local(object, r_sym, GOT_TYPE_STANDARD);
- if (is_new)
- {
- // If we are generating a shared object, we need to add a
- // dynamic RELATIVE relocation for this symbol's GOT entry.
- if (parameters->options().output_is_position_independent())
- {
- Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+ if (is_new)
+ {
+ // If we are generating a shared object, we need to add a
+ // dynamic RELATIVE relocation for this symbol's GOT entry.
+ if (parameters->options().output_is_position_independent())
+ {
+ Reloc_section* rel_dyn = target->rel_dyn_section(layout);
unsigned int got_offset =
object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
rel_dyn->add_local_relative(object, r_sym,
elfcpp::R_386_RELATIVE,
got, got_offset);
- }
- }
+ }
+ }
}
break;
@@ -1663,24 +1853,24 @@ Target_i386::Scan::local(Symbol_table* symtab,
{
bool output_is_shared = parameters->options().shared();
const tls::Tls_optimization optimized_type
- = Target_i386::optimize_tls_reloc(!output_is_shared, r_type);
+ = Target_i386::optimize_tls_reloc(!output_is_shared, r_type);
switch (r_type)
{
case elfcpp::R_386_TLS_GD: // Global-dynamic
if (optimized_type == tls::TLSOPT_NONE)
{
- // Create a pair of GOT entries for the module index and
- // dtv-relative offset.
- Output_data_got<32, false>* got
- = target->got_section(symtab, layout);
- unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+ // Create a pair of GOT entries for the module index and
+ // dtv-relative offset.
+ Output_data_got<32, false>* got
+ = target->got_section(symtab, layout);
+ unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
unsigned int shndx = lsym.get_st_shndx();
bool is_ordinary;
shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
if (!is_ordinary)
object->error(_("local symbol %u has bad shndx %u"),
r_sym, shndx);
- else
+ else
got->add_local_pair_with_rel(object, r_sym, shndx,
GOT_TYPE_TLS_PAIR,
target->rel_dyn_section(layout),
@@ -1692,16 +1882,16 @@ Target_i386::Scan::local(Symbol_table* symtab,
case elfcpp::R_386_TLS_GOTDESC: // Global-dynamic (from ~oliva)
target->define_tls_base_symbol(symtab, layout);
- if (optimized_type == tls::TLSOPT_NONE)
- {
- // Create a double GOT entry with an R_386_TLS_DESC
- // reloc. The R_386_TLS_DESC reloc is resolved
- // lazily, so the GOT entry needs to be in an area in
- // .got.plt, not .got. Call got_section to make sure
- // the section has been created.
+ if (optimized_type == tls::TLSOPT_NONE)
+ {
+ // Create a double GOT entry with an R_386_TLS_DESC
+ // reloc. The R_386_TLS_DESC reloc is resolved
+ // lazily, so the GOT entry needs to be in an area in
+ // .got.plt, not .got. Call got_section to make sure
+ // the section has been created.
target->got_section(symtab, layout);
- Output_data_got<32, false>* got = target->got_tlsdesc_section();
- unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+ Output_data_got<32, false>* got = target->got_tlsdesc_section();
+ unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_DESC))
{
unsigned int got_offset = got->add_constant(0);
@@ -1716,9 +1906,9 @@ Target_i386::Scan::local(Symbol_table* symtab,
Reloc_section* rt = target->rel_tls_desc_section(layout);
rt->add_absolute(elfcpp::R_386_TLS_DESC, got, got_offset);
}
- }
- else if (optimized_type != tls::TLSOPT_TO_LE)
- unsupported_reloc_local(object, r_type);
+ }
+ else if (optimized_type != tls::TLSOPT_TO_LE)
+ unsupported_reloc_local(object, r_type);
break;
case elfcpp::R_386_TLS_DESC_CALL:
@@ -1727,8 +1917,8 @@ Target_i386::Scan::local(Symbol_table* symtab,
case elfcpp::R_386_TLS_LDM: // Local-dynamic
if (optimized_type == tls::TLSOPT_NONE)
{
- // Create a GOT entry for the module index.
- target->got_mod_index_entry(symtab, layout, object);
+ // Create a GOT entry for the module index.
+ target->got_mod_index_entry(symtab, layout, object);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_local(object, r_type);
@@ -1743,32 +1933,32 @@ Target_i386::Scan::local(Symbol_table* symtab,
layout->set_has_static_tls();
if (optimized_type == tls::TLSOPT_NONE)
{
- // For the R_386_TLS_IE relocation, we need to create a
- // dynamic relocation when building a shared library.
- if (r_type == elfcpp::R_386_TLS_IE
- && parameters->options().shared())
- {
- Reloc_section* rel_dyn = target->rel_dyn_section(layout);
- unsigned int r_sym
- = elfcpp::elf_r_sym<32>(reloc.get_r_info());
- rel_dyn->add_local_relative(object, r_sym,
- elfcpp::R_386_RELATIVE,
- output_section, data_shndx,
- reloc.get_r_offset());
- }
- // Create a GOT entry for the tp-relative offset.
- Output_data_got<32, false>* got
- = target->got_section(symtab, layout);
- unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
- unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_IE_32
- ? elfcpp::R_386_TLS_TPOFF32
- : elfcpp::R_386_TLS_TPOFF);
- unsigned int got_type = (r_type == elfcpp::R_386_TLS_IE_32
- ? GOT_TYPE_TLS_OFFSET
- : GOT_TYPE_TLS_NOFFSET);
- got->add_local_with_rel(object, r_sym, got_type,
- target->rel_dyn_section(layout),
- dyn_r_type);
+ // For the R_386_TLS_IE relocation, we need to create a
+ // dynamic relocation when building a shared library.
+ if (r_type == elfcpp::R_386_TLS_IE
+ && parameters->options().shared())
+ {
+ Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+ unsigned int r_sym
+ = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+ rel_dyn->add_local_relative(object, r_sym,
+ elfcpp::R_386_RELATIVE,
+ output_section, data_shndx,
+ reloc.get_r_offset());
+ }
+ // Create a GOT entry for the tp-relative offset.
+ Output_data_got<32, false>* got
+ = target->got_section(symtab, layout);
+ unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+ unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_IE_32
+ ? elfcpp::R_386_TLS_TPOFF32
+ : elfcpp::R_386_TLS_TPOFF);
+ unsigned int got_type = (r_type == elfcpp::R_386_TLS_IE_32
+ ? GOT_TYPE_TLS_OFFSET
+ : GOT_TYPE_TLS_NOFFSET);
+ got->add_local_with_rel(object, r_sym, got_type,
+ target->rel_dyn_section(layout),
+ dyn_r_type);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_local(object, r_type);
@@ -1779,15 +1969,15 @@ Target_i386::Scan::local(Symbol_table* symtab,
layout->set_has_static_tls();
if (output_is_shared)
{
- // We need to create a dynamic relocation.
- gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
- unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
- unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_LE_32
- ? elfcpp::R_386_TLS_TPOFF32
- : elfcpp::R_386_TLS_TPOFF);
- Reloc_section* rel_dyn = target->rel_dyn_section(layout);
- rel_dyn->add_local(object, r_sym, dyn_r_type, output_section,
- data_shndx, reloc.get_r_offset());
+ // We need to create a dynamic relocation.
+ gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
+ unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+ unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_LE_32
+ ? elfcpp::R_386_TLS_TPOFF32
+ : elfcpp::R_386_TLS_TPOFF);
+ Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+ rel_dyn->add_local(object, r_sym, dyn_r_type, output_section,
+ data_shndx, reloc.get_r_offset());
}
break;
@@ -1836,7 +2026,7 @@ Target_i386::Scan::possible_function_pointer_reloc(unsigned int r_type)
case elfcpp::R_386_GOTOFF:
case elfcpp::R_386_GOT32:
{
- return true;
+ return true;
}
default:
return false;
@@ -1878,14 +2068,14 @@ Target_i386::Scan::global_reloc_may_be_function_pointer(
inline void
Target_i386::Scan::global(Symbol_table* symtab,
- Layout* layout,
- Target_i386* target,
- Sized_relobj_file<32, false>* object,
- unsigned int data_shndx,
- Output_section* output_section,
- const elfcpp::Rel<32, false>& reloc,
- unsigned int r_type,
- Symbol* gsym)
+ Layout* layout,
+ Target_i386* target,
+ Sized_relobj_file<32, false>* object,
+ unsigned int data_shndx,
+ Output_section* output_section,
+ const elfcpp::Rel<32, false>& reloc,
+ unsigned int r_type,
+ Symbol* gsym)
{
// A STT_GNU_IFUNC symbol may require a PLT entry.
if (gsym->type() == elfcpp::STT_GNU_IFUNC
@@ -1903,25 +2093,25 @@ Target_i386::Scan::global(Symbol_table* symtab,
case elfcpp::R_386_16:
case elfcpp::R_386_8:
{
- // Make a PLT entry if necessary.
- if (gsym->needs_plt_entry())
- {
- target->make_plt_entry(symtab, layout, gsym);
- // Since this is not a PC-relative relocation, we may be
- // taking the address of a function. In that case we need to
- // set the entry in the dynamic symbol table to the address of
- // the PLT entry.
- if (gsym->is_from_dynobj() && !parameters->options().shared())
- gsym->set_needs_dynsym_value();
- }
- // Make a dynamic relocation if necessary.
- if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
- {
- if (gsym->may_need_copy_reloc())
- {
- target->copy_reloc(symtab, layout, object,
- data_shndx, output_section, gsym, reloc);
- }
+ // Make a PLT entry if necessary.
+ if (gsym->needs_plt_entry())
+ {
+ target->make_plt_entry(symtab, layout, gsym);
+ // Since this is not a PC-relative relocation, we may be
+ // taking the address of a function. In that case we need to
+ // set the entry in the dynamic symbol table to the address of
+ // the PLT entry.
+ if (gsym->is_from_dynobj() && !parameters->options().shared())
+ gsym->set_needs_dynsym_value();
+ }
+ // Make a dynamic relocation if necessary.
+ if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
+ {
+ if (gsym->may_need_copy_reloc())
+ {
+ target->copy_reloc(symtab, layout, object,
+ data_shndx, output_section, gsym, reloc);
+ }
else if (r_type == elfcpp::R_386_32
&& gsym->type() == elfcpp::STT_GNU_IFUNC
&& gsym->can_use_relative_reloc(false)
@@ -1940,21 +2130,21 @@ Target_i386::Scan::global(Symbol_table* symtab,
object, data_shndx,
reloc.get_r_offset());
}
- else if (r_type == elfcpp::R_386_32
- && gsym->can_use_relative_reloc(false))
- {
- Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+ else if (r_type == elfcpp::R_386_32
+ && gsym->can_use_relative_reloc(false))
+ {
+ Reloc_section* rel_dyn = target->rel_dyn_section(layout);
rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE,
output_section, object,
data_shndx, reloc.get_r_offset());
- }
- else
- {
- Reloc_section* rel_dyn = target->rel_dyn_section(layout);
- rel_dyn->add_global(gsym, r_type, output_section, object,
- data_shndx, reloc.get_r_offset());
- }
- }
+ }
+ else
+ {
+ Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+ rel_dyn->add_global(gsym, r_type, output_section, object,
+ data_shndx, reloc.get_r_offset());
+ }
+ }
}
break;
@@ -1962,42 +2152,42 @@ Target_i386::Scan::global(Symbol_table* symtab,
case elfcpp::R_386_PC16:
case elfcpp::R_386_PC8:
{
- // Make a PLT entry if necessary.
- if (gsym->needs_plt_entry())
- {
- // These relocations are used for function calls only in
- // non-PIC code. For a 32-bit relocation in a shared library,
- // we'll need a text relocation anyway, so we can skip the
- // PLT entry and let the dynamic linker bind the call directly
- // to the target. For smaller relocations, we should use a
- // PLT entry to ensure that the call can reach.
- if (!parameters->options().shared()
- || r_type != elfcpp::R_386_PC32)
- target->make_plt_entry(symtab, layout, gsym);
- }
- // Make a dynamic relocation if necessary.
- if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
- {
- if (gsym->may_need_copy_reloc())
- {
- target->copy_reloc(symtab, layout, object,
- data_shndx, output_section, gsym, reloc);
- }
- else
- {
- Reloc_section* rel_dyn = target->rel_dyn_section(layout);
- rel_dyn->add_global(gsym, r_type, output_section, object,
- data_shndx, reloc.get_r_offset());
- }
- }
+ // Make a PLT entry if necessary.
+ if (gsym->needs_plt_entry())
+ {
+ // These relocations are used for function calls only in
+ // non-PIC code. For a 32-bit relocation in a shared library,
+ // we'll need a text relocation anyway, so we can skip the
+ // PLT entry and let the dynamic linker bind the call directly
+ // to the target. For smaller relocations, we should use a
+ // PLT entry to ensure that the call can reach.
+ if (!parameters->options().shared()
+ || r_type != elfcpp::R_386_PC32)
+ target->make_plt_entry(symtab, layout, gsym);
+ }
+ // Make a dynamic relocation if necessary.
+ if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
+ {
+ if (gsym->may_need_copy_reloc())
+ {
+ target->copy_reloc(symtab, layout, object,
+ data_shndx, output_section, gsym, reloc);
+ }
+ else
+ {
+ Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+ rel_dyn->add_global(gsym, r_type, output_section, object,
+ data_shndx, reloc.get_r_offset());
+ }
+ }
}
break;
case elfcpp::R_386_GOT32:
{
- // The symbol requires a GOT entry.
- Output_data_got<32, false>* got = target->got_section(symtab, layout);
- if (gsym->final_value_is_known())
+ // The symbol requires a GOT entry.
+ Output_data_got<32, false>* got = target->got_section(symtab, layout);
+ if (gsym->final_value_is_known())
{
// For a STT_GNU_IFUNC symbol we want the PLT address.
if (gsym->type() == elfcpp::STT_GNU_IFUNC)
@@ -2005,11 +2195,11 @@ Target_i386::Scan::global(Symbol_table* symtab,
else
got->add_global(gsym, GOT_TYPE_STANDARD);
}
- else
- {
- // If this symbol is not fully resolved, we need to add a
- // GOT entry with a dynamic relocation.
- Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+ else
+ {
+ // If this symbol is not fully resolved, we need to add a
+ // GOT entry with a dynamic relocation.
+ Reloc_section* rel_dyn = target->rel_dyn_section(layout);
// Use a GLOB_DAT rather than a RELATIVE reloc if:
//
@@ -2023,17 +2213,17 @@ Target_i386::Scan::global(Symbol_table* symtab,
//
// 3) This is a STT_GNU_IFUNC symbol in position dependent
// code, again so that function address comparisons work.
- if (gsym->is_from_dynobj()
- || gsym->is_undefined()
- || gsym->is_preemptible()
+ if (gsym->is_from_dynobj()
+ || gsym->is_undefined()
+ || gsym->is_preemptible()
|| (gsym->visibility() == elfcpp::STV_PROTECTED
&& parameters->options().shared())
|| (gsym->type() == elfcpp::STT_GNU_IFUNC
&& parameters->options().output_is_position_independent()))
- got->add_global_with_rel(gsym, GOT_TYPE_STANDARD,
- rel_dyn, elfcpp::R_386_GLOB_DAT);
- else
- {
+ got->add_global_with_rel(gsym, GOT_TYPE_STANDARD,
+ rel_dyn, elfcpp::R_386_GLOB_DAT);
+ else
+ {
// For a STT_GNU_IFUNC symbol we want to write the PLT
// offset into the GOT, so that function pointer
// comparisons work correctly.
@@ -2049,14 +2239,14 @@ Target_i386::Scan::global(Symbol_table* symtab,
&& !parameters->options().shared())
gsym->set_needs_dynsym_value();
}
- if (is_new)
+ if (is_new)
{
unsigned int got_off = gsym->got_offset(GOT_TYPE_STANDARD);
rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE,
got, got_off);
}
- }
- }
+ }
+ }
}
break;
@@ -2069,8 +2259,8 @@ Target_i386::Scan::global(Symbol_table* symtab,
// if the symbol is defined in the output file and is protected
// or hidden.
if (gsym->is_defined()
- && !gsym->is_from_dynobj()
- && !gsym->is_preemptible())
+ && !gsym->is_from_dynobj()
+ && !gsym->is_preemptible())
break;
target->make_plt_entry(symtab, layout, gsym);
break;
@@ -2112,29 +2302,29 @@ Target_i386::Scan::global(Symbol_table* symtab,
{
const bool is_final = gsym->final_value_is_known();
const tls::Tls_optimization optimized_type
- = Target_i386::optimize_tls_reloc(is_final, r_type);
+ = Target_i386::optimize_tls_reloc(is_final, r_type);
switch (r_type)
{
case elfcpp::R_386_TLS_GD: // Global-dynamic
if (optimized_type == tls::TLSOPT_NONE)
{
- // Create a pair of GOT entries for the module index and
- // dtv-relative offset.
- Output_data_got<32, false>* got
- = target->got_section(symtab, layout);
- got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
- target->rel_dyn_section(layout),
- elfcpp::R_386_TLS_DTPMOD32,
- elfcpp::R_386_TLS_DTPOFF32);
+ // Create a pair of GOT entries for the module index and
+ // dtv-relative offset.
+ Output_data_got<32, false>* got
+ = target->got_section(symtab, layout);
+ got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
+ target->rel_dyn_section(layout),
+ elfcpp::R_386_TLS_DTPMOD32,
+ elfcpp::R_386_TLS_DTPOFF32);
}
else if (optimized_type == tls::TLSOPT_TO_IE)
{
- // Create a GOT entry for the tp-relative offset.
- Output_data_got<32, false>* got
- = target->got_section(symtab, layout);
- got->add_global_with_rel(gsym, GOT_TYPE_TLS_NOFFSET,
- target->rel_dyn_section(layout),
- elfcpp::R_386_TLS_TPOFF);
+ // Create a GOT entry for the tp-relative offset.
+ Output_data_got<32, false>* got
+ = target->got_section(symtab, layout);
+ got->add_global_with_rel(gsym, GOT_TYPE_TLS_NOFFSET,
+ target->rel_dyn_section(layout),
+ elfcpp::R_386_TLS_TPOFF);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_global(object, r_type, gsym);
@@ -2142,30 +2332,30 @@ Target_i386::Scan::global(Symbol_table* symtab,
case elfcpp::R_386_TLS_GOTDESC: // Global-dynamic (~oliva url)
target->define_tls_base_symbol(symtab, layout);
- if (optimized_type == tls::TLSOPT_NONE)
- {
- // Create a double GOT entry with an R_386_TLS_DESC
- // reloc. The R_386_TLS_DESC reloc is resolved
- // lazily, so the GOT entry needs to be in an area in
- // .got.plt, not .got. Call got_section to make sure
- // the section has been created.
+ if (optimized_type == tls::TLSOPT_NONE)
+ {
+ // Create a double GOT entry with an R_386_TLS_DESC
+ // reloc. The R_386_TLS_DESC reloc is resolved
+ // lazily, so the GOT entry needs to be in an area in
+ // .got.plt, not .got. Call got_section to make sure
+ // the section has been created.
target->got_section(symtab, layout);
- Output_data_got<32, false>* got = target->got_tlsdesc_section();
+ Output_data_got<32, false>* got = target->got_tlsdesc_section();
Reloc_section* rt = target->rel_tls_desc_section(layout);
- got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC, rt,
- elfcpp::R_386_TLS_DESC, 0);
- }
- else if (optimized_type == tls::TLSOPT_TO_IE)
- {
- // Create a GOT entry for the tp-relative offset.
- Output_data_got<32, false>* got
- = target->got_section(symtab, layout);
- got->add_global_with_rel(gsym, GOT_TYPE_TLS_NOFFSET,
- target->rel_dyn_section(layout),
- elfcpp::R_386_TLS_TPOFF);
- }
- else if (optimized_type != tls::TLSOPT_TO_LE)
- unsupported_reloc_global(object, r_type, gsym);
+ got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC, rt,
+ elfcpp::R_386_TLS_DESC, 0);
+ }
+ else if (optimized_type == tls::TLSOPT_TO_IE)
+ {
+ // Create a GOT entry for the tp-relative offset.
+ Output_data_got<32, false>* got
+ = target->got_section(symtab, layout);
+ got->add_global_with_rel(gsym, GOT_TYPE_TLS_NOFFSET,
+ target->rel_dyn_section(layout),
+ elfcpp::R_386_TLS_TPOFF);
+ }
+ else if (optimized_type != tls::TLSOPT_TO_LE)
+ unsupported_reloc_global(object, r_type, gsym);
break;
case elfcpp::R_386_TLS_DESC_CALL:
@@ -2174,8 +2364,8 @@ Target_i386::Scan::global(Symbol_table* symtab,
case elfcpp::R_386_TLS_LDM: // Local-dynamic
if (optimized_type == tls::TLSOPT_NONE)
{
- // Create a GOT entry for the module index.
- target->got_mod_index_entry(symtab, layout, object);
+ // Create a GOT entry for the module index.
+ target->got_mod_index_entry(symtab, layout, object);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_global(object, r_type, gsym);
@@ -2190,29 +2380,29 @@ Target_i386::Scan::global(Symbol_table* symtab,
layout->set_has_static_tls();
if (optimized_type == tls::TLSOPT_NONE)
{
- // For the R_386_TLS_IE relocation, we need to create a
- // dynamic relocation when building a shared library.
- if (r_type == elfcpp::R_386_TLS_IE
- && parameters->options().shared())
- {
- Reloc_section* rel_dyn = target->rel_dyn_section(layout);
- rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE,
- output_section, object,
- data_shndx,
- reloc.get_r_offset());
- }
- // Create a GOT entry for the tp-relative offset.
- Output_data_got<32, false>* got
- = target->got_section(symtab, layout);
- unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_IE_32
- ? elfcpp::R_386_TLS_TPOFF32
- : elfcpp::R_386_TLS_TPOFF);
- unsigned int got_type = (r_type == elfcpp::R_386_TLS_IE_32
- ? GOT_TYPE_TLS_OFFSET
- : GOT_TYPE_TLS_NOFFSET);
- got->add_global_with_rel(gsym, got_type,
- target->rel_dyn_section(layout),
- dyn_r_type);
+ // For the R_386_TLS_IE relocation, we need to create a
+ // dynamic relocation when building a shared library.
+ if (r_type == elfcpp::R_386_TLS_IE
+ && parameters->options().shared())
+ {
+ Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+ rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE,
+ output_section, object,
+ data_shndx,
+ reloc.get_r_offset());
+ }
+ // Create a GOT entry for the tp-relative offset.
+ Output_data_got<32, false>* got
+ = target->got_section(symtab, layout);
+ unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_IE_32
+ ? elfcpp::R_386_TLS_TPOFF32
+ : elfcpp::R_386_TLS_TPOFF);
+ unsigned int got_type = (r_type == elfcpp::R_386_TLS_IE_32
+ ? GOT_TYPE_TLS_OFFSET
+ : GOT_TYPE_TLS_NOFFSET);
+ got->add_global_with_rel(gsym, got_type,
+ target->rel_dyn_section(layout),
+ dyn_r_type);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_global(object, r_type, gsym);
@@ -2223,13 +2413,13 @@ Target_i386::Scan::global(Symbol_table* symtab,
layout->set_has_static_tls();
if (parameters->options().shared())
{
- // We need to create a dynamic relocation.
- unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_LE_32
- ? elfcpp::R_386_TLS_TPOFF32
- : elfcpp::R_386_TLS_TPOFF);
- Reloc_section* rel_dyn = target->rel_dyn_section(layout);
- rel_dyn->add_global(gsym, dyn_r_type, output_section, object,
- data_shndx, reloc.get_r_offset());
+ // We need to create a dynamic relocation.
+ unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_LE_32
+ ? elfcpp::R_386_TLS_TPOFF32
+ : elfcpp::R_386_TLS_TPOFF);
+ Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+ rel_dyn->add_global(gsym, dyn_r_type, output_section, object,
+ data_shndx, reloc.get_r_offset());
}
break;
@@ -2259,20 +2449,20 @@ Target_i386::Scan::global(Symbol_table* symtab,
void
Target_i386::gc_process_relocs(Symbol_table* symtab,
- Layout* layout,
- Sized_relobj_file<32, false>* object,
- unsigned int data_shndx,
- unsigned int,
- const unsigned char* prelocs,
- size_t reloc_count,
- Output_section* output_section,
- bool needs_special_offset_handling,
- size_t local_symbol_count,
- const unsigned char* plocal_symbols)
+ Layout* layout,
+ Sized_relobj_file<32, false>* object,
+ unsigned int data_shndx,
+ unsigned int,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ size_t local_symbol_count,
+ const unsigned char* plocal_symbols)
{
gold::gc_process_relocs<32, false, Target_i386, elfcpp::SHT_REL,
- Target_i386::Scan,
- Target_i386::Relocatable_size_for_reloc>(
+ Target_i386::Scan,
+ Target_i386::Relocatable_size_for_reloc>(
symtab,
layout,
this,
@@ -2290,16 +2480,16 @@ Target_i386::gc_process_relocs(Symbol_table* symtab,
void
Target_i386::scan_relocs(Symbol_table* symtab,
- Layout* layout,
- Sized_relobj_file<32, false>* object,
- unsigned int data_shndx,
- unsigned int sh_type,
- const unsigned char* prelocs,
- size_t reloc_count,
- Output_section* output_section,
- bool needs_special_offset_handling,
- size_t local_symbol_count,
- const unsigned char* plocal_symbols)
+ Layout* layout,
+ Sized_relobj_file<32, false>* object,
+ unsigned int data_shndx,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ size_t local_symbol_count,
+ const unsigned char* plocal_symbols)
{
if (sh_type == elfcpp::SHT_RELA)
{
@@ -2401,8 +2591,8 @@ Target_i386::do_finalize_sections(
inline bool
Target_i386::Relocate::should_apply_static_reloc(const Sized_symbol<32>* gsym,
- unsigned int r_type,
- bool is_32bit,
+ unsigned int r_type,
+ bool is_32bit,
Output_section* output_section)
{
// If the output section is not allocated, then we didn't call
@@ -2419,8 +2609,8 @@ Target_i386::Relocate::should_apply_static_reloc(const Sized_symbol<32>* gsym,
// (c) the relocation is not 32 bits wide.
if (gsym == NULL)
return !(parameters->options().output_is_position_independent()
- && (ref_flags & Symbol::ABSOLUTE_REF)
- && !is_32bit);
+ && (ref_flags & Symbol::ABSOLUTE_REF)
+ && !is_32bit);
// For global symbols, we use the same helper routines used in the
// scan pass. If we did not create a dynamic relocation, or if we
@@ -2428,8 +2618,8 @@ Target_i386::Relocate::should_apply_static_reloc(const Sized_symbol<32>* gsym,
// relocation.
bool has_dyn = gsym->needs_dynamic_reloc(ref_flags);
bool is_rel = (ref_flags & Symbol::ABSOLUTE_REF)
- && gsym->can_use_relative_reloc(ref_flags
- & Symbol::FUNCTION_CALL);
+ && gsym->can_use_relative_reloc(ref_flags
+ & Symbol::FUNCTION_CALL);
return !has_dyn || is_rel;
}
@@ -2437,21 +2627,21 @@ Target_i386::Relocate::should_apply_static_reloc(const Sized_symbol<32>* gsym,
inline bool
Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
- Target_i386* target,
- Output_section* output_section,
- size_t relnum,
- const elfcpp::Rel<32, false>& rel,
- unsigned int r_type,
- const Sized_symbol<32>* gsym,
- const Symbol_value<32>* psymval,
- unsigned char* view,
- elfcpp::Elf_types<32>::Elf_Addr address,
- section_size_type view_size)
+ Target_i386* target,
+ Output_section* output_section,
+ size_t relnum,
+ const elfcpp::Rel<32, false>& rel,
+ unsigned int r_type,
+ const Sized_symbol<32>* gsym,
+ const Symbol_value<32>* psymval,
+ unsigned char* view,
+ elfcpp::Elf_types<32>::Elf_Addr address,
+ section_size_type view_size)
{
if (this->skip_call_tls_get_addr_)
{
if ((r_type != elfcpp::R_386_PLT32
- && r_type != elfcpp::R_386_PC32)
+ && r_type != elfcpp::R_386_PC32)
|| gsym == NULL
|| strcmp(gsym->name(), "___tls_get_addr") != 0)
gold_error_at_location(relinfo, relnum, rel.get_r_offset(),
@@ -2507,18 +2697,18 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
{
case elfcpp::R_386_GOT32:
if (gsym != NULL)
- {
- gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
- got_offset = (gsym->got_offset(GOT_TYPE_STANDARD)
- - target->got_size());
- }
+ {
+ gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
+ got_offset = (gsym->got_offset(GOT_TYPE_STANDARD)
+ - target->got_size());
+ }
else
- {
- unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
- got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
- - target->got_size());
- }
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
+ gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
+ got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
+ - target->got_size());
+ }
have_got_offset = true;
break;
@@ -2535,32 +2725,32 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
case elfcpp::R_386_32:
if (should_apply_static_reloc(gsym, r_type, true, output_section))
- Relocate_functions<32, false>::rel32(view, object, psymval);
+ Relocate_functions<32, false>::rel32(view, object, psymval);
break;
case elfcpp::R_386_PC32:
if (should_apply_static_reloc(gsym, r_type, true, output_section))
- Relocate_functions<32, false>::pcrel32(view, object, psymval, address);
+ Relocate_functions<32, false>::pcrel32(view, object, psymval, address);
break;
case elfcpp::R_386_16:
if (should_apply_static_reloc(gsym, r_type, false, output_section))
- Relocate_functions<32, false>::rel16(view, object, psymval);
+ Relocate_functions<32, false>::rel16(view, object, psymval);
break;
case elfcpp::R_386_PC16:
if (should_apply_static_reloc(gsym, r_type, false, output_section))
- Relocate_functions<32, false>::pcrel16(view, object, psymval, address);
+ Relocate_functions<32, false>::pcrel16(view, object, psymval, address);
break;
case elfcpp::R_386_8:
if (should_apply_static_reloc(gsym, r_type, false, output_section))
- Relocate_functions<32, false>::rel8(view, object, psymval);
+ Relocate_functions<32, false>::rel8(view, object, psymval);
break;
case elfcpp::R_386_PC8:
if (should_apply_static_reloc(gsym, r_type, false, output_section))
- Relocate_functions<32, false>::pcrel8(view, object, psymval, address);
+ Relocate_functions<32, false>::pcrel8(view, object, psymval, address);
break;
case elfcpp::R_386_PLT32:
@@ -2625,7 +2815,7 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
case elfcpp::R_386_TLS_LE: // Local-exec
case elfcpp::R_386_TLS_LE_32:
this->relocate_tls(relinfo, target, relnum, rel, r_type, gsym, psymval,
- view, address, view_size);
+ view, address, view_size);
break;
case elfcpp::R_386_32PLT:
@@ -2652,7 +2842,7 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
inline void
Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
- Target_i386* target,
+ Target_i386* target,
size_t relnum,
const elfcpp::Rel<32, false>& rel,
unsigned int r_type,
@@ -2690,43 +2880,37 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
break;
}
else
- {
- unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
- ? GOT_TYPE_TLS_NOFFSET
- : GOT_TYPE_TLS_PAIR);
- unsigned int got_offset;
- if (gsym != NULL)
- {
- gold_assert(gsym->has_got_offset(got_type));
- got_offset = gsym->got_offset(got_type) - target->got_size();
- }
- else
- {
- unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym, got_type));
- got_offset = (object->local_got_offset(r_sym, got_type)
+ {
+ unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
+ ? GOT_TYPE_TLS_NOFFSET
+ : GOT_TYPE_TLS_PAIR);
+ unsigned int got_offset;
+ if (gsym != NULL)
+ {
+ gold_assert(gsym->has_got_offset(got_type));
+ got_offset = gsym->got_offset(got_type) - target->got_size();
+ }
+ else
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
+ gold_assert(object->local_has_got_offset(r_sym, got_type));
+ got_offset = (object->local_got_offset(r_sym, got_type)
- target->got_size());
- }
- if (optimized_type == tls::TLSOPT_TO_IE)
+ }
+ if (optimized_type == tls::TLSOPT_TO_IE)
{
- if (tls_segment == NULL)
- {
- gold_assert(parameters->errors()->error_count() > 0
- || issue_undefined_symbol_error(gsym));
- return;
- }
this->tls_gd_to_ie(relinfo, relnum, tls_segment, rel, r_type,
- got_offset, view, view_size);
- break;
+ got_offset, view, view_size);
+ break;
+ }
+ else if (optimized_type == tls::TLSOPT_NONE)
+ {
+ // Relocate the field with the offset of the pair of GOT
+ // entries.
+ Relocate_functions<32, false>::rel32(view, got_offset);
+ break;
}
- else if (optimized_type == tls::TLSOPT_NONE)
- {
- // Relocate the field with the offset of the pair of GOT
- // entries.
- Relocate_functions<32, false>::rel32(view, got_offset);
- break;
- }
- }
+ }
gold_error_at_location(relinfo, relnum, rel.get_r_offset(),
_("unsupported reloc %u"),
r_type);
@@ -2736,7 +2920,7 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
case elfcpp::R_386_TLS_DESC_CALL:
this->local_dynamic_type_ = LOCAL_DYNAMIC_GNU;
if (optimized_type == tls::TLSOPT_TO_LE)
- {
+ {
if (tls_segment == NULL)
{
gold_assert(parameters->errors()->error_count() > 0
@@ -2744,16 +2928,16 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
return;
}
this->tls_desc_gd_to_le(relinfo, relnum, tls_segment,
- rel, r_type, value, view,
- view_size);
+ rel, r_type, value, view,
+ view_size);
break;
- }
+ }
else
- {
- unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
- ? GOT_TYPE_TLS_NOFFSET
- : GOT_TYPE_TLS_DESC);
- unsigned int got_offset = 0;
+ {
+ unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
+ ? GOT_TYPE_TLS_NOFFSET
+ : GOT_TYPE_TLS_DESC);
+ unsigned int got_offset = 0;
if (r_type == elfcpp::R_386_TLS_GOTDESC
&& optimized_type == tls::TLSOPT_NONE)
{
@@ -2763,19 +2947,19 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
got_offset = (target->got_size()
+ target->got_plt_section()->data_size());
}
- if (gsym != NULL)
- {
- gold_assert(gsym->has_got_offset(got_type));
- got_offset += gsym->got_offset(got_type) - target->got_size();
- }
- else
- {
- unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym, got_type));
- got_offset += (object->local_got_offset(r_sym, got_type)
+ if (gsym != NULL)
+ {
+ gold_assert(gsym->has_got_offset(got_type));
+ got_offset += gsym->got_offset(got_type) - target->got_size();
+ }
+ else
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
+ gold_assert(object->local_has_got_offset(r_sym, got_type));
+ got_offset += (object->local_got_offset(r_sym, got_type)
- target->got_size());
- }
- if (optimized_type == tls::TLSOPT_TO_IE)
+ }
+ if (optimized_type == tls::TLSOPT_TO_IE)
{
if (tls_segment == NULL)
{
@@ -2784,20 +2968,20 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
return;
}
this->tls_desc_gd_to_ie(relinfo, relnum, tls_segment, rel, r_type,
- got_offset, view, view_size);
- break;
+ got_offset, view, view_size);
+ break;
+ }
+ else if (optimized_type == tls::TLSOPT_NONE)
+ {
+ if (r_type == elfcpp::R_386_TLS_GOTDESC)
+ {
+ // Relocate the field with the offset of the pair of GOT
+ // entries.
+ Relocate_functions<32, false>::rel32(view, got_offset);
+ }
+ break;
}
- else if (optimized_type == tls::TLSOPT_NONE)
- {
- if (r_type == elfcpp::R_386_TLS_GOTDESC)
- {
- // Relocate the field with the offset of the pair of GOT
- // entries.
- Relocate_functions<32, false>::rel32(view, got_offset);
- }
- break;
- }
- }
+ }
gold_error_at_location(relinfo, relnum, rel.get_r_offset(),
_("unsupported reloc %u"),
r_type);
@@ -2825,15 +3009,15 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
break;
}
else if (optimized_type == tls::TLSOPT_NONE)
- {
- // Relocate the field with the offset of the GOT entry for
- // the module index.
- unsigned int got_offset;
- got_offset = (target->got_mod_index_entry(NULL, NULL, NULL)
+ {
+ // Relocate the field with the offset of the GOT entry for
+ // the module index.
+ unsigned int got_offset;
+ got_offset = (target->got_mod_index_entry(NULL, NULL, NULL)
- target->got_size());
- Relocate_functions<32, false>::rel32(view, got_offset);
- break;
- }
+ Relocate_functions<32, false>::rel32(view, got_offset);
+ break;
+ }
gold_error_at_location(relinfo, relnum, rel.get_r_offset(),
_("unsupported reloc %u"),
r_type);
@@ -2879,33 +3063,33 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
break;
}
else if (optimized_type == tls::TLSOPT_NONE)
- {
- // Relocate the field with the offset of the GOT entry for
- // the tp-relative offset of the symbol.
+ {
+ // Relocate the field with the offset of the GOT entry for
+ // the tp-relative offset of the symbol.
unsigned int got_type = (r_type == elfcpp::R_386_TLS_IE_32
- ? GOT_TYPE_TLS_OFFSET
- : GOT_TYPE_TLS_NOFFSET);
- unsigned int got_offset;
- if (gsym != NULL)
- {
- gold_assert(gsym->has_got_offset(got_type));
- got_offset = gsym->got_offset(got_type);
- }
- else
- {
- unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym, got_type));
- got_offset = object->local_got_offset(r_sym, got_type);
- }
- // For the R_386_TLS_IE relocation, we need to apply the
- // absolute address of the GOT entry.
- if (r_type == elfcpp::R_386_TLS_IE)
- got_offset += target->got_plt_section()->address();
- // All GOT offsets are relative to the end of the GOT.
- got_offset -= target->got_size();
- Relocate_functions<32, false>::rel32(view, got_offset);
- break;
- }
+ ? GOT_TYPE_TLS_OFFSET
+ : GOT_TYPE_TLS_NOFFSET);
+ unsigned int got_offset;
+ if (gsym != NULL)
+ {
+ gold_assert(gsym->has_got_offset(got_type));
+ got_offset = gsym->got_offset(got_type);
+ }
+ else
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
+ gold_assert(object->local_has_got_offset(r_sym, got_type));
+ got_offset = object->local_got_offset(r_sym, got_type);
+ }
+ // For the R_386_TLS_IE relocation, we need to apply the
+ // absolute address of the GOT entry.
+ if (r_type == elfcpp::R_386_TLS_IE)
+ got_offset += target->got_plt_section()->address();
+ // All GOT offsets are relative to the end of the GOT.
+ got_offset -= target->got_size();
+ Relocate_functions<32, false>::rel32(view, got_offset);
+ break;
+ }
gold_error_at_location(relinfo, relnum, rel.get_r_offset(),
_("unsupported reloc %u"),
r_type);
@@ -2915,32 +3099,32 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
// If we're creating a shared library, a dynamic relocation will
// have been created for this location, so do not apply it now.
if (!parameters->options().shared())
- {
+ {
if (tls_segment == NULL)
{
gold_assert(parameters->errors()->error_count() > 0
|| issue_undefined_symbol_error(gsym));
return;
}
- value -= tls_segment->memsz();
- Relocate_functions<32, false>::rel32(view, value);
- }
+ value -= tls_segment->memsz();
+ Relocate_functions<32, false>::rel32(view, value);
+ }
break;
case elfcpp::R_386_TLS_LE_32:
// If we're creating a shared library, a dynamic relocation will
// have been created for this location, so do not apply it now.
if (!parameters->options().shared())
- {
+ {
if (tls_segment == NULL)
{
gold_assert(parameters->errors()->error_count() > 0
|| issue_undefined_symbol_error(gsym));
return;
}
- value = tls_segment->memsz() - value;
- Relocate_functions<32, false>::rel32(view, value);
- }
+ value = tls_segment->memsz() - value;
+ Relocate_functions<32, false>::rel32(view, value);
+ }
break;
}
}
@@ -2970,7 +3154,7 @@ Target_i386::Relocate::tls_gd_to_le(const Relocate_info<32, false>* relinfo,
unsigned char op2 = view[-2];
tls::check_tls(relinfo, relnum, rel.get_r_offset(),
- op2 == 0x8d || op2 == 0x04);
+ op2 == 0x8d || op2 == 0x04);
tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[4] == 0xe8);
int roff = 5;
@@ -2980,15 +3164,15 @@ Target_i386::Relocate::tls_gd_to_le(const Relocate_info<32, false>* relinfo,
tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -3);
tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[-3] == 0x8d);
tls::check_tls(relinfo, relnum, rel.get_r_offset(),
- ((op1 & 0xc7) == 0x05 && op1 != (4 << 3)));
+ ((op1 & 0xc7) == 0x05 && op1 != (4 << 3)));
memcpy(view - 3, "\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12);
}
else
{
tls::check_tls(relinfo, relnum, rel.get_r_offset(),
- (op1 & 0xf8) == 0x80 && (op1 & 7) != 4);
+ (op1 & 0xf8) == 0x80 && (op1 & 7) != 4);
if (rel.get_r_offset() + 9 < view_size
- && view[9] == 0x90)
+ && view[9] == 0x90)
{
// There is a trailing nop. Use the size byte subl.
memcpy(view - 2, "\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12);
@@ -3032,7 +3216,7 @@ Target_i386::Relocate::tls_gd_to_ie(const Relocate_info<32, false>* relinfo,
unsigned char op2 = view[-2];
tls::check_tls(relinfo, relnum, rel.get_r_offset(),
- op2 == 0x8d || op2 == 0x04);
+ op2 == 0x8d || op2 == 0x04);
tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[4] == 0xe8);
int roff = 5;
@@ -3045,24 +3229,24 @@ Target_i386::Relocate::tls_gd_to_ie(const Relocate_info<32, false>* relinfo,
tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -3);
tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[-3] == 0x8d);
tls::check_tls(relinfo, relnum, rel.get_r_offset(),
- ((op1 & 0xc7) == 0x05 && op1 != (4 << 3)));
+ ((op1 & 0xc7) == 0x05 && op1 != (4 << 3)));
memcpy(view - 3, "\x65\xa1\0\0\0\0\x03\x83\0\0\0", 12);
}
else
{
tls::check_tls(relinfo, relnum, rel.get_r_offset(),
- (op1 & 0xf8) == 0x80 && (op1 & 7) != 4);
+ (op1 & 0xf8) == 0x80 && (op1 & 7) != 4);
if (rel.get_r_offset() + 9 < view_size
- && view[9] == 0x90)
+ && view[9] == 0x90)
{
- // FIXME: This is not the right instruction sequence.
+ // FIXME: This is not the right instruction sequence.
// There is a trailing nop. Use the size byte subl.
memcpy(view - 2, "\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12);
roff = 6;
}
else
{
- // FIXME: This is not the right instruction sequence.
+ // FIXME: This is not the right instruction sequence.
// Use the five byte subl.
memcpy(view - 2, "\x65\xa1\0\0\0\0\x2d\0\0\0", 11);
}
@@ -3096,7 +3280,7 @@ Target_i386::Relocate::tls_desc_gd_to_le(
tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -2);
tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 4);
tls::check_tls(relinfo, relnum, rel.get_r_offset(),
- view[-2] == 0x8d && view[-1] == 0x83);
+ view[-2] == 0x8d && view[-1] == 0x83);
view[-1] = 0x05;
value -= tls_segment->memsz();
Relocate_functions<32, false>::rel32(view, value);
@@ -3108,7 +3292,7 @@ Target_i386::Relocate::tls_desc_gd_to_le(
gold_assert(r_type == elfcpp::R_386_TLS_DESC_CALL);
tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 2);
tls::check_tls(relinfo, relnum, rel.get_r_offset(),
- view[0] == 0xff && view[1] == 0x10);
+ view[0] == 0xff && view[1] == 0x10);
view[0] = 0x66;
view[1] = 0x90;
}
@@ -3135,7 +3319,7 @@ Target_i386::Relocate::tls_desc_gd_to_ie(
tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -2);
tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 4);
tls::check_tls(relinfo, relnum, rel.get_r_offset(),
- view[-2] == 0x8d && view[-1] == 0x83);
+ view[-2] == 0x8d && view[-1] == 0x83);
view[-2] = 0x8b;
Relocate_functions<32, false>::rel32(view, value);
}
@@ -3146,7 +3330,7 @@ Target_i386::Relocate::tls_desc_gd_to_ie(
gold_assert(r_type == elfcpp::R_386_TLS_DESC_CALL);
tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 2);
tls::check_tls(relinfo, relnum, rel.get_r_offset(),
- view[0] == 0xff && view[1] == 0x10);
+ view[0] == 0xff && view[1] == 0x10);
view[0] = 0x66;
view[1] = 0x90;
}
@@ -3173,7 +3357,7 @@ Target_i386::Relocate::tls_ld_to_le(const Relocate_info<32, false>* relinfo,
// FIXME: Does this test really always pass?
tls::check_tls(relinfo, relnum, rel.get_r_offset(),
- view[-2] == 0x8d && view[-1] == 0x83);
+ view[-2] == 0x8d && view[-1] == 0x83);
tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[4] == 0xe8);
@@ -3223,7 +3407,7 @@ Target_i386::Relocate::tls_ie_to_le(const Relocate_info<32, false>* relinfo,
{
// movl XX,%reg ==> movl $YY,%reg
tls::check_tls(relinfo, relnum, rel.get_r_offset(),
- (op1 & 0xc7) == 0x05);
+ (op1 & 0xc7) == 0x05);
view[-2] = 0xc7;
view[-1] = 0xc0 | ((op1 >> 3) & 7);
}
@@ -3231,7 +3415,7 @@ Target_i386::Relocate::tls_ie_to_le(const Relocate_info<32, false>* relinfo,
{
// addl XX,%reg ==> addl $YY,%reg
tls::check_tls(relinfo, relnum, rel.get_r_offset(),
- (op1 & 0xc7) == 0x05);
+ (op1 & 0xc7) == 0x05);
view[-2] = 0x81;
view[-1] = 0xc0 | ((op1 >> 3) & 7);
}
@@ -3250,7 +3434,7 @@ Target_i386::Relocate::tls_ie_to_le(const Relocate_info<32, false>* relinfo,
unsigned char op1 = view[-1];
unsigned char op2 = view[-2];
tls::check_tls(relinfo, relnum, rel.get_r_offset(),
- (op1 & 0xc0) == 0x80 && (op1 & 7) != 4);
+ (op1 & 0xc0) == 0x80 && (op1 & 7) != 4);
if (op2 == 0x8b)
{
// movl %gs:XX(%reg1),%reg2 ==> movl $YY,%reg2
@@ -3476,7 +3660,7 @@ Target_i386::do_code_fill(section_size_type length) const
jmp[0] = 0xe9;
elfcpp::Swap_unaligned<32, false>::writeval(jmp + 1, length - 5);
return (std::string(reinterpret_cast<char*>(&jmp[0]), 5)
- + std::string(length - 5, '\0'));
+ + std::string(length - 5, static_cast<char>(0x90)));
}
// Nop sequences of various lengths.
@@ -3486,45 +3670,45 @@ Target_i386::do_code_fill(section_size_type length) const
const char nop4[4] = { '\x8d', '\x74', '\x26', // leal 0(%esi,1),%esi
'\x00'};
const char nop5[5] = { '\x90', '\x8d', '\x74', // nop
- '\x26', '\x00' }; // leal 0(%esi,1),%esi
+ '\x26', '\x00' }; // leal 0(%esi,1),%esi
const char nop6[6] = { '\x8d', '\xb6', '\x00', // leal 0L(%esi),%esi
- '\x00', '\x00', '\x00' };
+ '\x00', '\x00', '\x00' };
const char nop7[7] = { '\x8d', '\xb4', '\x26', // leal 0L(%esi,1),%esi
- '\x00', '\x00', '\x00',
+ '\x00', '\x00', '\x00',
'\x00' };
const char nop8[8] = { '\x90', '\x8d', '\xb4', // nop
- '\x26', '\x00', '\x00', // leal 0L(%esi,1),%esi
+ '\x26', '\x00', '\x00', // leal 0L(%esi,1),%esi
'\x00', '\x00' };
const char nop9[9] = { '\x89', '\xf6', '\x8d', // movl %esi,%esi
- '\xbc', '\x27', '\x00', // leal 0L(%edi,1),%edi
+ '\xbc', '\x27', '\x00', // leal 0L(%edi,1),%edi
'\x00', '\x00', '\x00' };
const char nop10[10] = { '\x8d', '\x76', '\x00', // leal 0(%esi),%esi
- '\x8d', '\xbc', '\x27', // leal 0L(%edi,1),%edi
+ '\x8d', '\xbc', '\x27', // leal 0L(%edi,1),%edi
'\x00', '\x00', '\x00',
'\x00' };
const char nop11[11] = { '\x8d', '\x74', '\x26', // leal 0(%esi,1),%esi
- '\x00', '\x8d', '\xbc', // leal 0L(%edi,1),%edi
+ '\x00', '\x8d', '\xbc', // leal 0L(%edi,1),%edi
'\x27', '\x00', '\x00',
'\x00', '\x00' };
const char nop12[12] = { '\x8d', '\xb6', '\x00', // leal 0L(%esi),%esi
- '\x00', '\x00', '\x00', // leal 0L(%edi),%edi
+ '\x00', '\x00', '\x00', // leal 0L(%edi),%edi
'\x8d', '\xbf', '\x00',
'\x00', '\x00', '\x00' };
const char nop13[13] = { '\x8d', '\xb6', '\x00', // leal 0L(%esi),%esi
- '\x00', '\x00', '\x00', // leal 0L(%edi,1),%edi
+ '\x00', '\x00', '\x00', // leal 0L(%edi,1),%edi
'\x8d', '\xbc', '\x27',
'\x00', '\x00', '\x00',
- '\x00' };
+ '\x00' };
const char nop14[14] = { '\x8d', '\xb4', '\x26', // leal 0L(%esi,1),%esi
- '\x00', '\x00', '\x00', // leal 0L(%edi,1),%edi
+ '\x00', '\x00', '\x00', // leal 0L(%edi,1),%edi
'\x00', '\x8d', '\xbc',
'\x27', '\x00', '\x00',
- '\x00', '\x00' };
+ '\x00', '\x00' };
const char nop15[15] = { '\xeb', '\x0d', '\x90', // jmp .+15
- '\x90', '\x90', '\x90', // nop,nop,nop,...
+ '\x90', '\x90', '\x90', // nop,nop,nop,...
'\x90', '\x90', '\x90',
'\x90', '\x90', '\x90',
- '\x90', '\x90', '\x90' };
+ '\x90', '\x90', '\x90' };
const char* nops[16] = {
NULL,
@@ -3568,12 +3752,12 @@ Target_i386::do_is_call_to_non_split(const Symbol* sym, unsigned int) const
void
Target_i386::do_calls_non_split(Relobj* object, unsigned int shndx,
- section_offset_type fnoffset,
- section_size_type fnsize,
- unsigned char* view,
- section_size_type view_size,
- std::string* from,
- std::string* to) const
+ section_offset_type fnoffset,
+ section_size_type fnsize,
+ unsigned char* view,
+ section_size_type view_size,
+ std::string* from,
+ std::string* to) const
{
// The function starts with a comparison of the stack pointer and a
// field in the TCB. This is followed by a jump.
@@ -3620,7 +3804,8 @@ Target_i386::do_calls_non_split(Relobj* object, unsigned int shndx,
*to = "__morestack_non_split";
}
-// The selector for i386 object files.
+// The selector for i386 object files. Note this is never instantiated
+// directly. It's only used in Target_selector_i386_nacl, below.
class Target_selector_i386 : public Target_selector_freebsd
{
@@ -3636,6 +3821,327 @@ public:
{ return new Target_i386(); }
};
-Target_selector_i386 target_selector_i386;
+// NaCl variant. It uses different PLT contents.
+
+class Output_data_plt_i386_nacl : public Output_data_plt_i386
+{
+ public:
+ Output_data_plt_i386_nacl(Layout* layout,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative)
+ : Output_data_plt_i386(layout, plt_entry_size, got_plt, got_irelative)
+ { }
+
+ protected:
+ virtual unsigned int
+ do_get_plt_entry_size() const
+ { return plt_entry_size; }
+
+ virtual void
+ do_add_eh_frame(Layout* layout)
+ {
+ layout->add_eh_frame_for_plt(this, plt_eh_frame_cie, plt_eh_frame_cie_size,
+ plt_eh_frame_fde, plt_eh_frame_fde_size);
+ }
+
+ // The size of an entry in the PLT.
+ static const int plt_entry_size = 64;
+
+ // The .eh_frame unwind information for the PLT.
+ static const int plt_eh_frame_fde_size = 32;
+ static const unsigned char plt_eh_frame_fde[plt_eh_frame_fde_size];
+};
+
+class Output_data_plt_i386_nacl_exec : public Output_data_plt_i386_nacl
+{
+public:
+ Output_data_plt_i386_nacl_exec(Layout* layout,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative)
+ : Output_data_plt_i386_nacl(layout, got_plt, got_irelative)
+ { }
+
+ protected:
+ virtual void
+ do_fill_first_plt_entry(unsigned char* pov,
+ elfcpp::Elf_types<32>::Elf_Addr got_address);
+
+ virtual unsigned int
+ do_fill_plt_entry(unsigned char* pov,
+ elfcpp::Elf_types<32>::Elf_Addr got_address,
+ unsigned int got_offset,
+ unsigned int plt_offset,
+ unsigned int plt_rel_offset);
+
+ private:
+ // The first entry in the PLT for an executable.
+ static const unsigned char first_plt_entry[plt_entry_size];
+
+ // Other entries in the PLT for an executable.
+ static const unsigned char plt_entry[plt_entry_size];
+};
+
+class Output_data_plt_i386_nacl_dyn : public Output_data_plt_i386_nacl
+{
+ public:
+ Output_data_plt_i386_nacl_dyn(Layout* layout,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative)
+ : Output_data_plt_i386_nacl(layout, got_plt, got_irelative)
+ { }
+
+ protected:
+ virtual void
+ do_fill_first_plt_entry(unsigned char* pov, elfcpp::Elf_types<32>::Elf_Addr);
+
+ virtual unsigned int
+ do_fill_plt_entry(unsigned char* pov,
+ elfcpp::Elf_types<32>::Elf_Addr,
+ unsigned int got_offset,
+ unsigned int plt_offset,
+ unsigned int plt_rel_offset);
+
+ private:
+ // The first entry in the PLT for a shared object.
+ static const unsigned char first_plt_entry[plt_entry_size];
+
+ // Other entries in the PLT for a shared object.
+ static const unsigned char plt_entry[plt_entry_size];
+};
+
+class Target_i386_nacl : public Target_i386
+{
+ public:
+ Target_i386_nacl()
+ : Target_i386(&i386_nacl_info)
+ { }
+
+ protected:
+ virtual Output_data_plt_i386*
+ do_make_data_plt(Layout* layout,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative,
+ bool dyn)
+ {
+ if (dyn)
+ return new Output_data_plt_i386_nacl_dyn(layout, got_plt, got_irelative);
+ else
+ return new Output_data_plt_i386_nacl_exec(layout, got_plt, got_irelative);
+ }
+
+ private:
+ static const Target::Target_info i386_nacl_info;
+};
+
+const Target::Target_info Target_i386_nacl::i386_nacl_info =
+{
+ 32, // size
+ false, // is_big_endian
+ elfcpp::EM_386, // machine_code
+ false, // has_make_symbol
+ false, // has_resolve
+ true, // has_code_fill
+ true, // is_default_stack_executable
+ true, // can_icf_inline_merge_sections
+ '\0', // wrap_char
+ "/lib/ld-nacl-x86-32.so.1", // dynamic_linker
+ 0x20000, // default_text_segment_address
+ 0x10000, // abi_pagesize (overridable by -z max-page-size)
+ 0x10000, // common_pagesize (overridable by -z common-page-size)
+ true, // isolate_execinstr
+ 0x10000000, // rosegment_gap
+ elfcpp::SHN_UNDEF, // small_common_shndx
+ elfcpp::SHN_UNDEF, // large_common_shndx
+ 0, // small_common_section_flags
+ 0, // large_common_section_flags
+ NULL, // attributes_section
+ NULL // attributes_vendor
+};
+
+#define NACLMASK 0xe0 // 32-byte alignment mask
+
+const unsigned char
+Output_data_plt_i386_nacl_exec::first_plt_entry[plt_entry_size] =
+{
+ 0xff, 0x35, // pushl contents of memory address
+ 0, 0, 0, 0, // replaced with address of .got + 4
+ 0x8b, 0x0d, // movl contents of address, %ecx
+ 0, 0, 0, 0, // replaced with address of .got + 8
+ 0x83, 0xe1, NACLMASK, // andl $NACLMASK, %ecx
+ 0xff, 0xe1, // jmp *%ecx
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nops
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nops
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nops
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nops
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nops
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nops
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, // nops
+ 0x90, 0x90, 0x90, 0x90, 0x90
+};
+
+void
+Output_data_plt_i386_nacl_exec::do_fill_first_plt_entry(
+ unsigned char* pov,
+ elfcpp::Elf_types<32>::Elf_Addr got_address)
+{
+ memcpy(pov, first_plt_entry, plt_entry_size);
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_address + 4);
+ elfcpp::Swap<32, false>::writeval(pov + 8, got_address + 8);
+}
+
+// The first entry in the PLT for a shared object.
+
+const unsigned char
+Output_data_plt_i386_nacl_dyn::first_plt_entry[plt_entry_size] =
+{
+ 0xff, 0xb3, 4, 0, 0, 0, // pushl 4(%ebx)
+ 0x8b, 0x4b, 0x08, // mov 0x8(%ebx), %ecx
+ 0x83, 0xe1, NACLMASK, // andl $NACLMASK, %ecx
+ 0xff, 0xe1, // jmp *%ecx
+ 0x90, 0x90, 0x90, 0x90, 0x90, // nops
+ 0x90, 0x90, 0x90, 0x90, 0x90, // nops
+ 0x90, 0x90, 0x90, 0x90, 0x90, // nops
+ 0x90, 0x90, 0x90, 0x90, 0x90, // nops
+ 0x90, 0x90, 0x90, 0x90, 0x90, // nops
+ 0x90, 0x90, 0x90, 0x90, 0x90, // nops
+ 0x90, 0x90, 0x90, 0x90, 0x90, // nops
+ 0x90, 0x90, 0x90, 0x90, 0x90, // nops
+ 0x90, 0x90, 0x90, 0x90, 0x90, // nops
+ 0x90, 0x90, 0x90, 0x90, 0x90 // nops
+};
+
+void
+Output_data_plt_i386_nacl_dyn::do_fill_first_plt_entry(
+ unsigned char* pov,
+ elfcpp::Elf_types<32>::Elf_Addr)
+{
+ memcpy(pov, first_plt_entry, plt_entry_size);
+}
+
+// Subsequent entries in the PLT for an executable.
+
+const unsigned char
+Output_data_plt_i386_nacl_exec::plt_entry[plt_entry_size] =
+{
+ 0x8b, 0x0d, // movl contents of address, %ecx */
+ 0, 0, 0, 0, // replaced with address of symbol in .got
+ 0x83, 0xe1, NACLMASK, // andl $NACLMASK, %ecx
+ 0xff, 0xe1, // jmp *%ecx
+
+ // Pad to the next 32-byte boundary with nop instructions.
+ 0x90,
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+
+ // Lazy GOT entries point here (32-byte aligned).
+ 0x68, // pushl immediate
+ 0, 0, 0, 0, // replaced with offset into relocation table
+ 0xe9, // jmp relative
+ 0, 0, 0, 0, // replaced with offset to start of .plt
+
+ // Pad to the next 32-byte boundary with nop instructions.
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+ 0x90, 0x90
+};
+
+unsigned int
+Output_data_plt_i386_nacl_exec::do_fill_plt_entry(
+ unsigned char* pov,
+ elfcpp::Elf_types<32>::Elf_Addr got_address,
+ unsigned int got_offset,
+ unsigned int plt_offset,
+ unsigned int plt_rel_offset)
+{
+ memcpy(pov, plt_entry, plt_entry_size);
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
+ got_address + got_offset);
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 33, plt_rel_offset);
+ elfcpp::Swap<32, false>::writeval(pov + 38, - (plt_offset + 38 + 4));
+ return 32;
+}
+
+// Subsequent entries in the PLT for a shared object.
+
+const unsigned char
+Output_data_plt_i386_nacl_dyn::plt_entry[plt_entry_size] =
+{
+ 0x8b, 0x8b, // movl offset(%ebx), %ecx
+ 0, 0, 0, 0, // replaced with offset of symbol in .got
+ 0x83, 0xe1, 0xe0, // andl $NACLMASK, %ecx
+ 0xff, 0xe1, // jmp *%ecx
+
+ // Pad to the next 32-byte boundary with nop instructions.
+ 0x90,
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+
+ // Lazy GOT entries point here (32-byte aligned).
+ 0x68, // pushl immediate
+ 0, 0, 0, 0, // replaced with offset into relocation table.
+ 0xe9, // jmp relative
+ 0, 0, 0, 0, // replaced with offset to start of .plt.
+
+ // Pad to the next 32-byte boundary with nop instructions.
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+ 0x90, 0x90
+};
+
+unsigned int
+Output_data_plt_i386_nacl_dyn::do_fill_plt_entry(
+ unsigned char* pov,
+ elfcpp::Elf_types<32>::Elf_Addr,
+ unsigned int got_offset,
+ unsigned int plt_offset,
+ unsigned int plt_rel_offset)
+{
+ memcpy(pov, plt_entry, plt_entry_size);
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_offset);
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 33, plt_rel_offset);
+ elfcpp::Swap<32, false>::writeval(pov + 38, - (plt_offset + 38 + 4));
+ return 32;
+}
+
+const unsigned char
+Output_data_plt_i386_nacl::plt_eh_frame_fde[plt_eh_frame_fde_size] =
+{
+ 0, 0, 0, 0, // Replaced with offset to .plt.
+ 0, 0, 0, 0, // Replaced with size of .plt.
+ 0, // Augmentation size.
+ elfcpp::DW_CFA_def_cfa_offset, 8, // DW_CFA_def_cfa_offset: 8.
+ elfcpp::DW_CFA_advance_loc + 6, // Advance 6 to __PLT__ + 6.
+ elfcpp::DW_CFA_def_cfa_offset, 12, // DW_CFA_def_cfa_offset: 12.
+ elfcpp::DW_CFA_advance_loc + 58, // Advance 58 to __PLT__ + 64.
+ elfcpp::DW_CFA_def_cfa_expression, // DW_CFA_def_cfa_expression.
+ 13, // Block length.
+ elfcpp::DW_OP_breg4, 4, // Push %esp + 4.
+ elfcpp::DW_OP_breg8, 0, // Push %eip.
+ elfcpp::DW_OP_const1u, 63, // Push 0x3f.
+ elfcpp::DW_OP_and, // & (%eip & 0x3f).
+ elfcpp::DW_OP_const1u, 37, // Push 0x25.
+ elfcpp::DW_OP_ge, // >= ((%eip & 0x3f) >= 0x25)
+ elfcpp::DW_OP_lit2, // Push 2.
+ elfcpp::DW_OP_shl, // << (((%eip & 0x3f) >= 0x25) << 2)
+ elfcpp::DW_OP_plus, // + ((((%eip&0x3f)>=0x25)<<2)+%esp+4
+ elfcpp::DW_CFA_nop, // Align to 32 bytes.
+ elfcpp::DW_CFA_nop
+};
+
+// The selector for i386-nacl object files.
+
+class Target_selector_i386_nacl
+ : public Target_selector_nacl<Target_selector_i386, Target_i386_nacl>
+{
+ public:
+ Target_selector_i386_nacl()
+ : Target_selector_nacl<Target_selector_i386,
+ Target_i386_nacl>("x86-32",
+ "elf32-i386-nacl",
+ "elf_i386_nacl")
+ { }
+};
+
+Target_selector_i386_nacl target_selector_i386;
} // End anonymous namespace.
diff --git a/binutils-2.22/gold/incremental-dump.cc b/binutils-2.22/gold/incremental-dump.cc
index fb3d25f..5365265 100644
--- a/binutils-2.22/gold/incremental-dump.cc
+++ b/binutils-2.22/gold/incremental-dump.cc
@@ -52,6 +52,9 @@ find_input_containing_global(
unsigned int* symndx)
{
typedef Incremental_inputs_reader<size, big_endian> Inputs_reader;
+ static const unsigned int global_sym_entry_size =
+ Incremental_inputs_reader<size, big_endian>::global_sym_entry_size;
+
for (unsigned int i = 0; i < incremental_inputs.input_file_count(); ++i)
{
typename Inputs_reader::Incremental_input_entry_reader input_file =
@@ -63,7 +66,8 @@ find_input_containing_global(
if (offset >= input_file.get_symbol_offset(0)
&& offset < input_file.get_symbol_offset(nsyms))
{
- *symndx = (offset - input_file.get_symbol_offset(0)) / 20;
+ *symndx = ((offset - input_file.get_symbol_offset(0))
+ / global_sym_entry_size);
return input_file;
}
}
@@ -92,7 +96,7 @@ dump_incremental_inputs(const char* argv0, const char* filename,
Incremental_inputs_reader<size, big_endian>
incremental_inputs(inc->inputs_reader());
- if (incremental_inputs.version() != 1)
+ if (incremental_inputs.version() != 2)
{
fprintf(stderr, "%s: %s: unknown incremental version %d\n", argv0,
filename, incremental_inputs.version());
diff --git a/binutils-2.22/gold/incremental.cc b/binutils-2.22/gold/incremental.cc
index 0c33db1..acabaea 100644
--- a/binutils-2.22/gold/incremental.cc
+++ b/binutils-2.22/gold/incremental.cc
@@ -1,6 +1,6 @@
// inremental.cc -- incremental linking support for gold
-// Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
// Written by Mikolaj Zalewski <mikolajz@google.com>.
// This file is part of gold.
@@ -41,9 +41,10 @@
namespace gold {
-// Version information. Will change frequently during the development, later
-// we could think about backward (and forward?) compatibility.
-const unsigned int INCREMENTAL_LINK_VERSION = 1;
+// Version number for the .gnu_incremental_inputs section.
+// Version 1 was the initial checkin.
+// Version 2 adds some padding to ensure 8-byte alignment where necessary.
+const unsigned int INCREMENTAL_LINK_VERSION = 2;
// This class manages the .gnu_incremental_inputs section, which holds
// the header information, a directory of input files, and separate
@@ -112,8 +113,18 @@ class Output_section_incremental_inputs : public Output_section_data
// Sizes of various structures.
static const int sizeof_addr = size / 8;
- static const int header_size = 16;
- static const int input_entry_size = 24;
+ static const int header_size =
+ Incremental_inputs_reader<size, big_endian>::header_size;
+ static const int input_entry_size =
+ Incremental_inputs_reader<size, big_endian>::input_entry_size;
+ static const unsigned int object_info_size =
+ Incremental_inputs_reader<size, big_endian>::object_info_size;
+ static const unsigned int input_section_entry_size =
+ Incremental_inputs_reader<size, big_endian>::input_section_entry_size;
+ static const unsigned int global_sym_entry_size =
+ Incremental_inputs_reader<size, big_endian>::global_sym_entry_size;
+ static const unsigned int incr_reloc_size =
+ Incremental_relocs_reader<size, big_endian>::reloc_size;
// The Incremental_inputs object.
const Incremental_inputs* inputs_;
@@ -132,7 +143,7 @@ vexplain_no_incremental(const char* format, va_list args)
if (vasprintf(&buf, format, args) < 0)
gold_nomem();
gold_info(_("the link might take longer: "
- "cannot perform incremental link: %s"), buf);
+ "cannot perform incremental link: %s"), buf);
free(buf);
}
@@ -285,7 +296,7 @@ Sized_incremental_binary<size, big_endian>::setup_readers()
unsigned int main_strtab_shndx =
this->elf_file_.section_link(main_symtab_shndx);
gold_assert(main_strtab_shndx != elfcpp::SHN_UNDEF
- && main_strtab_shndx < this->elf_file_.shnum());
+ && main_strtab_shndx < this->elf_file_.shnum());
this->main_strtab_loc_ = this->elf_file_.section_contents(main_strtab_shndx);
// Walk the list of input files (a) to setup an Input_reader for each
@@ -311,7 +322,7 @@ Sized_incremental_binary<size, big_endian>::setup_readers()
case INCREMENTAL_INPUT_ARCHIVE:
{
Incremental_library* lib =
- new Incremental_library(input_file.filename(), i,
+ new Incremental_library(input_file.filename(), i,
&this->input_entry_readers_[i]);
this->library_map_[i] = lib;
unsigned int member_count = input_file.get_member_count();
@@ -371,16 +382,16 @@ check_input_args(std::vector<const Input_argument*>& input_args_map,
check_input_args(input_args_map, lib->begin(), lib->end());
}
else
- {
- gold_assert(p->is_file());
- unsigned int arg_serial = p->file().arg_serial();
- if (arg_serial > 0)
+ {
+ gold_assert(p->is_file());
+ unsigned int arg_serial = p->file().arg_serial();
+ if (arg_serial > 0)
{
gold_assert(arg_serial <= input_args_map.size());
gold_assert(input_args_map[arg_serial - 1] == 0);
input_args_map[arg_serial - 1] = &*p;
}
- }
+ }
}
}
@@ -410,11 +421,11 @@ Sized_incremental_binary<size, big_endian>::do_check_inputs(
if (incremental_inputs->command_line() != inputs.command_line())
{
gold_debug(DEBUG_INCREMENTAL,
- "old command line: %s",
- inputs.command_line());
+ "old command line: %s",
+ inputs.command_line());
gold_debug(DEBUG_INCREMENTAL,
- "new command line: %s",
- incremental_inputs->command_line().c_str());
+ "new command line: %s",
+ incremental_inputs->command_line().c_str());
explain_no_incremental(_("command line changed"));
return false;
}
@@ -535,14 +546,14 @@ Sized_incremental_binary<size, big_endian>::do_init_layout(Layout* layout)
Shdr shdr(pshdr);
const char* name;
if (!shstrtab.get_c_string(shdr.get_sh_name(), &name))
- name = NULL;
+ name = NULL;
gold_debug(DEBUG_INCREMENTAL,
"Output section: %2d %08lx %08lx %08lx %3d %s",
- i,
- static_cast<long>(shdr.get_sh_addr()),
- static_cast<long>(shdr.get_sh_offset()),
- static_cast<long>(shdr.get_sh_size()),
- shdr.get_sh_type(), name ? name : "<null>");
+ i,
+ static_cast<long>(shdr.get_sh_addr()),
+ static_cast<long>(shdr.get_sh_offset()),
+ static_cast<long>(shdr.get_sh_size()),
+ shdr.get_sh_type(), name ? name : "<null>");
this->section_map_[i] = layout->init_fixed_output_section(name, shdr);
pshdr += shdr_size;
}
@@ -572,7 +583,7 @@ Sized_incremental_binary<size, big_endian>::do_reserve_layout(
{
bool is_def;
bool is_copy;
- unsigned int output_symndx =
+ unsigned int output_symndx =
input_file.get_output_symbol_index(i, &is_def, &is_copy);
if (is_copy)
{
@@ -581,7 +592,7 @@ Sized_incremental_binary<size, big_endian>::do_reserve_layout(
elfcpp::Sym<size, big_endian> gsym(sym_p);
unsigned int shndx = gsym.get_st_shndx();
if (shndx < 1 || shndx >= this->section_map_.size())
- continue;
+ continue;
Output_section* os = this->section_map_[shndx];
off_t offset = gsym.get_st_value() - os->address();
os->reserve(offset, gsym.get_st_size());
@@ -599,9 +610,9 @@ Sized_incremental_binary<size, big_endian>::do_reserve_layout(
for (unsigned int i = 0; i < shnum; i++)
{
typename Input_entry_reader::Input_section_info sect =
- input_file.get_input_section(i);
+ input_file.get_input_section(i);
if (sect.output_shndx == 0 || sect.sh_offset == -1)
- continue;
+ continue;
Output_section* os = this->section_map_[sect.output_shndx];
gold_assert(os != NULL);
os->reserve(sect.sh_offset, sect.sh_size);
@@ -632,7 +643,7 @@ Sized_incremental_binary<size, big_endian>::do_process_got_plt(
// Tell the target how big the GOT and PLT sections are.
unsigned int got_count = got_plt_reader.get_got_entry_count();
unsigned int plt_count = got_plt_reader.get_plt_entry_count();
- Output_data_got<size, big_endian>* got =
+ Output_data_got_base* got =
target->init_got_plt_for_update(symtab, layout, got_count, plt_count);
// Read the GOT entries from the base file and build the outgoing GOT.
@@ -685,7 +696,7 @@ Sized_incremental_binary<size, big_endian>::do_process_got_plt(
gold_assert(plt_desc >= first_global && plt_desc < symtab_count);
Symbol* sym = this->global_symbol(plt_desc - first_global);
// Add the PLT entry only if the symbol is still referenced.
- if (sym->in_reg())
+ if (sym != NULL && sym->in_reg())
{
gold_debug(DEBUG_INCREMENTAL,
"PLT entry %d: %s",
@@ -770,7 +781,7 @@ Sized_incremental_binary<size, big_endian>::do_apply_incremental_relocs(
// output file.
unsigned int offset = isymtab.get_list_head(i);
while (offset > 0)
- {
+ {
Incremental_global_symbol_reader<big_endian> sym_info =
this->inputs_reader().global_symbol_reader_at_offset(offset);
unsigned int r_base = sym_info.reloc_offset();
@@ -792,12 +803,12 @@ Sized_incremental_binary<size, big_endian>::do_apply_incremental_relocs(
view_size);
gold_debug(DEBUG_INCREMENTAL,
- " %08lx: %s + %d: type %d addend %ld",
- (long)(section_offset + r_offset),
- os->name(),
- (int)r_offset,
- r_type,
- (long)r_addend);
+ " %08lx: %s + %d: type %d addend %ld",
+ (long)(section_offset + r_offset),
+ os->name(),
+ (int)r_offset,
+ r_type,
+ (long)r_addend);
target->apply_relocation(&relinfo, r_offset, r_type, r_addend,
gsym, view, address, view_size);
@@ -807,7 +818,7 @@ Sized_incremental_binary<size, big_endian>::do_apply_incremental_relocs(
of->write_output_view(section_offset, view_size, view);
}
offset = sym_info.next_offset();
- }
+ }
}
}
@@ -837,15 +848,16 @@ namespace
template<int size, bool big_endian>
Incremental_binary*
make_sized_incremental_binary(Output_file* file,
- const elfcpp::Ehdr<size, big_endian>& ehdr)
+ const elfcpp::Ehdr<size, big_endian>& ehdr)
{
- Target* target = select_target(ehdr.get_e_machine(), size, big_endian,
- ehdr.get_e_ident()[elfcpp::EI_OSABI],
- ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]);
+ Target* target = select_target(NULL, 0, // XXX
+ ehdr.get_e_machine(), size, big_endian,
+ ehdr.get_e_ident()[elfcpp::EI_OSABI],
+ ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]);
if (target == NULL)
{
explain_no_incremental(_("unsupported ELF machine number %d"),
- ehdr.get_e_machine());
+ ehdr.get_e_machine());
return NULL;
}
@@ -882,7 +894,7 @@ open_incremental_binary(Output_file* file)
bool big_endian = false;
std::string error;
if (!elfcpp::Elf_recognizer::is_valid_header(p, want, &size, &big_endian,
- &error))
+ &error))
{
explain_no_incremental(error.c_str());
return NULL;
@@ -892,44 +904,44 @@ open_incremental_binary(Output_file* file)
if (size == 32)
{
if (big_endian)
- {
+ {
#ifdef HAVE_TARGET_32_BIG
- result = make_sized_incremental_binary<32, true>(
- file, elfcpp::Ehdr<32, true>(p));
+ result = make_sized_incremental_binary<32, true>(
+ file, elfcpp::Ehdr<32, true>(p));
#else
- explain_no_incremental(_("unsupported file: 32-bit, big-endian"));
+ explain_no_incremental(_("unsupported file: 32-bit, big-endian"));
#endif
- }
+ }
else
- {
+ {
#ifdef HAVE_TARGET_32_LITTLE
- result = make_sized_incremental_binary<32, false>(
- file, elfcpp::Ehdr<32, false>(p));
+ result = make_sized_incremental_binary<32, false>(
+ file, elfcpp::Ehdr<32, false>(p));
#else
- explain_no_incremental(_("unsupported file: 32-bit, little-endian"));
+ explain_no_incremental(_("unsupported file: 32-bit, little-endian"));
#endif
- }
+ }
}
else if (size == 64)
{
if (big_endian)
- {
+ {
#ifdef HAVE_TARGET_64_BIG
- result = make_sized_incremental_binary<64, true>(
- file, elfcpp::Ehdr<64, true>(p));
+ result = make_sized_incremental_binary<64, true>(
+ file, elfcpp::Ehdr<64, true>(p));
#else
- explain_no_incremental(_("unsupported file: 64-bit, big-endian"));
+ explain_no_incremental(_("unsupported file: 64-bit, big-endian"));
#endif
- }
+ }
else
- {
+ {
#ifdef HAVE_TARGET_64_LITTLE
- result = make_sized_incremental_binary<64, false>(
- file, elfcpp::Ehdr<64, false>(p));
+ result = make_sized_incremental_binary<64, false>(
+ file, elfcpp::Ehdr<64, false>(p));
#else
- explain_no_incremental(_("unsupported file: 64-bit, little-endian"));
+ explain_no_incremental(_("unsupported file: 64-bit, little-endian"));
#endif
- }
+ }
}
else
gold_unreachable();
@@ -964,7 +976,7 @@ Incremental_inputs::report_command_line(int argc, const char* const* argv)
|| is_prefix_of("--incremental-base=", argv[i])
|| is_prefix_of("--incremental-patch=", argv[i])
|| is_prefix_of("--debug=", argv[i]))
- continue;
+ continue;
if (strcmp(argv[i], "--incremental-base") == 0
|| strcmp(argv[i], "--incremental-patch") == 0
|| strcmp(argv[i], "--debug") == 0)
@@ -979,20 +991,20 @@ Incremental_inputs::report_command_line(int argc, const char* const* argv)
// Now append argv[i], but with all single-quotes escaped
const char* argpos = argv[i];
while (1)
- {
- const int len = strcspn(argpos, "'");
- args.append(argpos, len);
- if (argpos[len] == '\0')
- break;
- args.append("'\"'\"'");
- argpos += len + 1;
- }
+ {
+ const int len = strcspn(argpos, "'");
+ args.append(argpos, len);
+ if (argpos[len] == '\0')
+ break;
+ args.append("'\"'\"'");
+ argpos += len + 1;
+ }
args.append("'");
}
this->command_line_ = args;
this->strtab_->add(this->command_line_.c_str(), false,
- &this->command_line_key_);
+ &this->command_line_key_);
}
// Record the input archive file ARCHIVE. This is called by the
@@ -1094,7 +1106,7 @@ Incremental_inputs::report_object(Object* obj, unsigned int arg_serial,
if (!obj->is_dynamic())
{
this->current_object_entry_ =
- new Incremental_object_entry(filename_key, obj, arg_serial, mtime);
+ new Incremental_object_entry(filename_key, obj, arg_serial, mtime);
input_entry = this->current_object_entry_;
if (arch != NULL)
{
@@ -1193,37 +1205,44 @@ Incremental_inputs::finalize()
void
Incremental_inputs::create_data_sections(Symbol_table* symtab)
{
+ int reloc_align = 4;
+
switch (parameters->size_and_endianness())
{
#ifdef HAVE_TARGET_32_LITTLE
case Parameters::TARGET_32_LITTLE:
this->inputs_section_ =
- new Output_section_incremental_inputs<32, false>(this, symtab);
+ new Output_section_incremental_inputs<32, false>(this, symtab);
+ reloc_align = 4;
break;
#endif
#ifdef HAVE_TARGET_32_BIG
case Parameters::TARGET_32_BIG:
this->inputs_section_ =
- new Output_section_incremental_inputs<32, true>(this, symtab);
+ new Output_section_incremental_inputs<32, true>(this, symtab);
+ reloc_align = 4;
break;
#endif
#ifdef HAVE_TARGET_64_LITTLE
case Parameters::TARGET_64_LITTLE:
this->inputs_section_ =
- new Output_section_incremental_inputs<64, false>(this, symtab);
+ new Output_section_incremental_inputs<64, false>(this, symtab);
+ reloc_align = 8;
break;
#endif
#ifdef HAVE_TARGET_64_BIG
case Parameters::TARGET_64_BIG:
this->inputs_section_ =
- new Output_section_incremental_inputs<64, true>(this, symtab);
+ new Output_section_incremental_inputs<64, true>(this, symtab);
+ reloc_align = 8;
break;
#endif
default:
gold_unreachable();
}
this->symtab_section_ = new Output_data_space(4, "** incremental_symtab");
- this->relocs_section_ = new Output_data_space(4, "** incremental_relocs");
+ this->relocs_section_ = new Output_data_space(reloc_align,
+ "** incremental_relocs");
this->got_plt_section_ = new Output_data_space(4, "** incremental_got_plt");
}
@@ -1244,8 +1263,6 @@ void
Output_section_incremental_inputs<size, big_endian>::set_final_data_size()
{
const Incremental_inputs* inputs = this->inputs_;
- const unsigned int sizeof_addr = size / 8;
- const unsigned int rel_size = 8 + 2 * sizeof_addr;
// Offset of each input entry.
unsigned int input_offset = this->header_size;
@@ -1289,13 +1306,13 @@ Output_section_incremental_inputs<size, big_endian>::set_final_data_size()
// Input section count, global symbol count, local symbol offset,
// local symbol count, first dynamic reloc, dynamic reloc count,
// comdat group count.
- info_offset += 28;
+ info_offset += this->object_info_size;
// Each input section.
info_offset += (entry->get_input_section_count()
- * (8 + 2 * sizeof_addr));
+ * this->input_section_entry_size);
// Each global symbol.
const Object::Symbols* syms = entry->object()->get_global_symbols();
- info_offset += syms->size() * 20;
+ info_offset += syms->size() * this->global_sym_entry_size;
// Each comdat group.
info_offset += entry->get_comdat_group_count() * 4;
}
@@ -1319,8 +1336,8 @@ Output_section_incremental_inputs<size, big_endian>::set_final_data_size()
continue;
if (sym->is_forwarder())
sym = this->symtab_->resolve_forwards(sym);
- if (sym->symtab_index() != -1U)
- ++nsyms_out;
+ if (sym->symtab_index() != -1U)
+ ++nsyms_out;
}
info_offset += nsyms_out * 4;
}
@@ -1341,7 +1358,11 @@ Output_section_incremental_inputs<size, big_endian>::set_final_data_size()
default:
gold_unreachable();
}
- }
+
+ // Pad so each supplemental info block begins at an 8-byte boundary.
+ if (info_offset & 4)
+ info_offset += 4;
+ }
this->set_data_size(info_offset);
@@ -1351,7 +1372,7 @@ Output_section_incremental_inputs<size, big_endian>::set_final_data_size()
// Set the size of the .gnu_incremental_relocs section.
inputs->relocs_section()->set_current_data_size(inputs->get_reloc_count()
- * rel_size);
+ * this->incr_reloc_size);
// Set the size of the .gnu_incremental_got_plt section.
Sized_target<size, big_endian>* target =
@@ -1411,7 +1432,7 @@ Output_section_incremental_inputs<size, big_endian>::do_write(Output_file* of)
gold_assert(pov - oview == oview_size);
// Write the .gnu_incremental_symtab section.
- gold_assert( static_cast<off_t>(global_sym_count) * 4 == symtab_size);
+ gold_assert(global_sym_count * 4 == symtab_size);
this->write_symtab(symtab_view, global_syms, global_sym_count);
delete[] global_syms;
@@ -1442,6 +1463,7 @@ Output_section_incremental_inputs<size, big_endian>::write_header(
Swap32::writeval(pov + 4, input_file_count);
Swap32::writeval(pov + 8, command_line_offset);
Swap32::writeval(pov + 12, 0);
+ gold_assert(this->header_size == 16);
return pov + this->header_size;
}
@@ -1463,19 +1485,20 @@ Output_section_incremental_inputs<size, big_endian>::write_input_files(
{
gold_assert(static_cast<unsigned int>(pov - oview) == (*p)->get_offset());
section_offset_type filename_offset =
- strtab->get_offset_from_key((*p)->get_filename_key());
+ strtab->get_offset_from_key((*p)->get_filename_key());
const Timespec& mtime = (*p)->get_mtime();
unsigned int flags = (*p)->type();
if ((*p)->is_in_system_directory())
- flags |= INCREMENTAL_INPUT_IN_SYSTEM_DIR;
+ flags |= INCREMENTAL_INPUT_IN_SYSTEM_DIR;
if ((*p)->as_needed())
- flags |= INCREMENTAL_INPUT_AS_NEEDED;
+ flags |= INCREMENTAL_INPUT_AS_NEEDED;
Swap32::writeval(pov, filename_offset);
Swap32::writeval(pov + 4, (*p)->get_info_offset());
Swap64::writeval(pov + 8, mtime.seconds);
Swap32::writeval(pov + 16, mtime.nanoseconds);
Swap16::writeval(pov + 20, flags);
Swap16::writeval(pov + 22, (*p)->arg_serial());
+ gold_assert(this->input_entry_size == 24);
pov += this->input_entry_size;
}
return pov;
@@ -1549,7 +1572,9 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
Swap32::writeval(pov + 16, first_dynrel);
Swap32::writeval(pov + 20, ndynrel);
Swap32::writeval(pov + 24, ncomdat);
- pov += 28;
+ Swap32::writeval(pov + 28, 0);
+ gold_assert(this->object_info_size == 32);
+ pov += this->object_info_size;
// Build a temporary array to map input section indexes
// from the original object file index to the index in the
@@ -1581,7 +1606,9 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
Swap32::writeval(pov + 4, out_shndx);
Swap::writeval(pov + 8, out_offset);
Swap::writeval(pov + 8 + sizeof_addr, sh_size);
- pov += 8 + 2 * sizeof_addr;
+ gold_assert(this->input_section_entry_size
+ == 8 + 2 * sizeof_addr);
+ pov += this->input_section_entry_size;
}
// For each global symbol, write its associated relocations,
@@ -1602,7 +1629,7 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
// but exclude linker-predefined symbols and symbols
// copied from shared objects.
if (!sym->is_predefined()
- && !sym->is_copied_from_dynobj())
+ && !sym->is_copied_from_dynobj())
shndx = -1U;
}
else if (sym->object() == obj && sym->is_defined())
@@ -1632,8 +1659,10 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
Swap32::writeval(pov + 4, shndx);
Swap32::writeval(pov + 8, chain);
Swap32::writeval(pov + 12, nrelocs);
- Swap32::writeval(pov + 16, first_reloc * 3 * sizeof_addr);
- pov += 20;
+ Swap32::writeval(pov + 16,
+ first_reloc * (8 + 2 * sizeof_addr));
+ gold_assert(this->global_sym_entry_size == 20);
+ pov += this->global_sym_entry_size;
}
// For each kept COMDAT group, write the group signature.
@@ -1682,8 +1711,8 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
continue;
if (sym->is_forwarder())
sym = this->symtab_->resolve_forwards(sym);
- if (sym->symtab_index() == -1U)
- continue;
+ if (sym->symtab_index() == -1U)
+ continue;
unsigned int flags = 0;
// If the symbol has hidden or internal visibility, we
// mark it as defined in the shared object so we don't
@@ -1744,6 +1773,13 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
default:
gold_unreachable();
}
+
+ // Pad the info block to a multiple of 8 bytes.
+ if (static_cast<unsigned int>(pov - oview) & 4)
+ {
+ Swap32::writeval(pov, 0);
+ pov += 4;
+ }
}
return pov;
}
@@ -1876,9 +1912,9 @@ class Global_symbol_visitor_got_plt
const Got_offset_list* got_offsets = sym->got_offset_list();
if (got_offsets != NULL)
{
- this->info_.sym_index = sym->symtab_index();
- this->info_.input_index = 0;
- Got_visitor v(this->info_);
+ this->info_.sym_index = sym->symtab_index();
+ this->info_.input_index = 0;
+ Got_visitor v(this->info_);
got_offsets->for_all_got_offsets(&v);
}
if (sym->has_plt_offset())
@@ -1966,8 +2002,9 @@ Sized_relobj_incr<size, big_endian>::Sized_relobj_incr(
input_reader_(ibase->inputs_reader().input_file(input_file_index)),
local_symbol_count_(0), output_local_dynsym_count_(0),
local_symbol_index_(0), local_symbol_offset_(0), local_dynsym_offset_(0),
- symbols_(), incr_reloc_offset_(-1U), incr_reloc_count_(0),
- incr_reloc_output_index_(0), incr_relocs_(NULL), local_symbols_()
+ symbols_(), defined_count_(0), incr_reloc_offset_(-1U),
+ incr_reloc_count_(0), incr_reloc_output_index_(0), incr_relocs_(NULL),
+ local_symbols_()
{
if (this->input_reader_.is_in_system_directory())
this->set_is_in_system_directory();
@@ -2000,19 +2037,36 @@ Sized_relobj_incr<size, big_endian>::do_layout(
Output_sections& out_sections(this->output_sections());
out_sections.resize(shnum);
this->section_offsets().resize(shnum);
+
+ // Keep track of .debug_info and .debug_types sections.
+ std::vector<unsigned int> debug_info_sections;
+ std::vector<unsigned int> debug_types_sections;
+
for (unsigned int i = 1; i < shnum; i++)
{
typename Input_entry_reader::Input_section_info sect =
- this->input_reader_.get_input_section(i - 1);
+ this->input_reader_.get_input_section(i - 1);
// Add the section to the incremental inputs layout.
incremental_inputs->report_input_section(this, i, sect.name,
sect.sh_size);
if (sect.output_shndx == 0 || sect.sh_offset == -1)
- continue;
+ continue;
Output_section* os = this->ibase_->output_section(sect.output_shndx);
gold_assert(os != NULL);
out_sections[i] = os;
this->section_offsets()[i] = static_cast<Address>(sect.sh_offset);
+
+ // When generating a .gdb_index section, we do additional
+ // processing of .debug_info and .debug_types sections after all
+ // the other sections.
+ if (parameters->options().gdb_index())
+ {
+ const char* name = os->name();
+ if (strcmp(name, ".debug_info") == 0)
+ debug_info_sections.push_back(i);
+ else if (strcmp(name, ".debug_types") == 0)
+ debug_types_sections.push_back(i);
+ }
}
// Process the COMDAT groups.
@@ -2021,15 +2075,34 @@ Sized_relobj_incr<size, big_endian>::do_layout(
{
const char* signature = this->input_reader_.get_comdat_group_signature(i);
if (signature == NULL || signature[0] == '\0')
- this->error(_("COMDAT group has no signature"));
+ this->error(_("COMDAT group has no signature"));
bool keep = layout->find_or_add_kept_section(signature, this, i, true,
true, NULL);
if (keep)
incremental_inputs->report_comdat_group(this, signature);
else
- this->error(_("COMDAT group %s included twice in incremental link"),
+ this->error(_("COMDAT group %s included twice in incremental link"),
signature);
}
+
+ // When building a .gdb_index section, scan the .debug_info and
+ // .debug_types sections.
+ for (std::vector<unsigned int>::const_iterator p
+ = debug_info_sections.begin();
+ p != debug_info_sections.end();
+ ++p)
+ {
+ unsigned int i = *p;
+ layout->add_to_gdb_index(false, this, NULL, 0, i, 0, 0);
+ }
+ for (std::vector<unsigned int>::const_iterator p
+ = debug_types_sections.begin();
+ p != debug_types_sections.end();
+ ++p)
+ {
+ unsigned int i = *p;
+ layout->add_to_gdb_index(true, this, 0, 0, i, 0, 0);
+ }
}
// Layout sections whose layout was deferred while waiting for
@@ -2088,7 +2161,7 @@ Sized_relobj_incr<size, big_endian>::do_add_symbols(
// Local hidden symbols start out as globals, but get converted to
// to local during output.
if (st_bind == elfcpp::STB_LOCAL)
- st_bind = elfcpp::STB_GLOBAL;
+ st_bind = elfcpp::STB_GLOBAL;
unsigned int input_shndx = info.shndx();
if (input_shndx == 0 || input_shndx == -1U)
@@ -2120,6 +2193,9 @@ Sized_relobj_incr<size, big_endian>::do_add_symbols(
Symbol* res = symtab->add_from_incrobj(this, name, NULL, &sym);
+ if (shndx != elfcpp::SHN_UNDEF)
+ ++this->defined_count_;
+
// If this is a linker-defined symbol that hasn't yet been defined,
// define it now.
if (input_shndx == -1U && !res->is_defined())
@@ -2188,22 +2264,39 @@ Sized_relobj_incr<size, big_endian>::do_section_size(unsigned int)
gold_unreachable();
}
-// Get the name of a section.
+// Get the name of a section. This returns the name of the output
+// section, because we don't usually track the names of the input
+// sections.
template<int size, bool big_endian>
std::string
-Sized_relobj_incr<size, big_endian>::do_section_name(unsigned int)
+Sized_relobj_incr<size, big_endian>::do_section_name(unsigned int shndx)
{
- gold_unreachable();
+ Output_sections& out_sections(this->output_sections());
+ Output_section* os = out_sections[shndx];
+ if (os == NULL)
+ return NULL;
+ return os->name();
}
// Return a view of the contents of a section.
template<int size, bool big_endian>
-Object::Location
-Sized_relobj_incr<size, big_endian>::do_section_contents(unsigned int)
+const unsigned char*
+Sized_relobj_incr<size, big_endian>::do_section_contents(
+ unsigned int shndx,
+ section_size_type* plen,
+ bool)
{
- gold_unreachable();
+ Output_sections& out_sections(this->output_sections());
+ Output_section* os = out_sections[shndx];
+ gold_assert(os != NULL);
+ off_t section_offset = os->offset();
+ typename Input_entry_reader::Input_section_info sect =
+ this->input_reader_.get_input_section(shndx - 1);
+ section_offset += sect.sh_offset;
+ *plen = sect.sh_size;
+ return this->ibase_->view(section_offset, sect.sh_size).data();
}
// Return section flags.
@@ -2283,9 +2376,21 @@ Sized_relobj_incr<size, big_endian>::do_initialize_xindex()
template<int size, bool big_endian>
void
Sized_relobj_incr<size, big_endian>::do_get_global_symbol_counts(
- const Symbol_table*, size_t*, size_t*) const
-{
- gold_unreachable();
+ const Symbol_table*,
+ size_t* defined,
+ size_t* used) const
+{
+ *defined = this->defined_count_;
+ size_t count = 0;
+ for (typename Symbols::const_iterator p = this->symbols_.begin();
+ p != this->symbols_.end();
+ ++p)
+ if (*p != NULL
+ && (*p)->source() == Symbol::FROM_OBJECT
+ && (*p)->object() == this
+ && (*p)->is_defined())
+ ++count;
+ *used = count;
}
// Read the relocs.
@@ -2382,7 +2487,7 @@ Sized_relobj_incr<size, big_endian>::do_count_local_symbols(
elfcpp::Sym<size, big_endian> sym(symp);
const char* name;
if (!strtab.get_c_string(sym.get_st_name(), &name))
- name = "";
+ name = "";
gold_debug(DEBUG_INCREMENTAL, "Local symbol %d: %s", i, name);
name = pool->add(name, true, NULL);
this->local_symbols_.push_back(Local_symbol(name,
@@ -2485,7 +2590,7 @@ Sized_relobj_incr<size, big_endian>::do_relocate(const Symbol_table*,
unsigned char* dyn_oview = NULL;
if (dyn_output_size > 0)
dyn_oview = of->get_output_view(this->local_dynsym_offset_,
- dyn_output_size);
+ dyn_output_size);
// Write the local symbols.
unsigned char* ov = oview;
@@ -2529,18 +2634,18 @@ Sized_relobj_incr<size, big_endian>::do_relocate(const Symbol_table*,
// Write the symbol to the output dynamic symbol table.
if (lsym.needs_dynsym_entry)
- {
- gold_assert(dyn_ov < dyn_oview + dyn_output_size);
- elfcpp::Sym_write<size, big_endian> osym(dyn_ov);
- osym.put_st_name(dynpool->get_offset(lsym.name));
- osym.put_st_value(lsym.st_value);
- osym.put_st_size(lsym.st_size);
+ {
+ gold_assert(dyn_ov < dyn_oview + dyn_output_size);
+ elfcpp::Sym_write<size, big_endian> osym(dyn_ov);
+ osym.put_st_name(dynpool->get_offset(lsym.name));
+ osym.put_st_value(lsym.st_value);
+ osym.put_st_size(lsym.st_size);
osym.put_st_info(elfcpp::STB_LOCAL,
static_cast<elfcpp::STT>(lsym.st_type));
- osym.put_st_other(0);
- osym.put_st_shndx(st_shndx);
- dyn_ov += sym_size;
- }
+ osym.put_st_other(0);
+ osym.put_st_shndx(st_shndx);
+ dyn_ov += sym_size;
+ }
}
if (output_size > 0)
@@ -2554,7 +2659,7 @@ Sized_relobj_incr<size, big_endian>::do_relocate(const Symbol_table*,
{
gold_assert(dyn_ov - dyn_oview == dyn_output_size);
of->write_output_view(this->local_dynsym_offset_, dyn_output_size,
- dyn_oview);
+ dyn_oview);
}
}
@@ -2579,7 +2684,7 @@ Sized_incr_dynobj<size, big_endian>::Sized_incr_dynobj(
: Dynobj(name, NULL), ibase_(ibase),
input_file_index_(input_file_index),
input_reader_(ibase->inputs_reader().input_file(input_file_index)),
- symbols_()
+ symbols_(), defined_count_(0)
{
if (this->input_reader_.is_in_system_directory())
this->set_is_in_system_directory();
@@ -2662,7 +2767,7 @@ Sized_incr_dynobj<size, big_endian>::do_add_symbols(
// Local hidden symbols start out as globals, but get converted to
// to local during output.
if (st_bind == elfcpp::STB_LOCAL)
- st_bind = elfcpp::STB_GLOBAL;
+ st_bind = elfcpp::STB_GLOBAL;
if (!is_def)
{
@@ -2675,6 +2780,7 @@ Sized_incr_dynobj<size, big_endian>::do_add_symbols(
// is meaningless, as long as it's not SHN_UNDEF.
shndx = 1;
v = gsym.get_st_value();
+ ++this->defined_count_;
}
osym.put_st_name(0);
@@ -2760,8 +2866,11 @@ Sized_incr_dynobj<size, big_endian>::do_section_name(unsigned int)
// Return a view of the contents of a section.
template<int size, bool big_endian>
-Object::Location
-Sized_incr_dynobj<size, big_endian>::do_section_contents(unsigned int)
+const unsigned char*
+Sized_incr_dynobj<size, big_endian>::do_section_contents(
+ unsigned int,
+ section_size_type*,
+ bool)
{
gold_unreachable();
}
@@ -2843,9 +2952,22 @@ Sized_incr_dynobj<size, big_endian>::do_initialize_xindex()
template<int size, bool big_endian>
void
Sized_incr_dynobj<size, big_endian>::do_get_global_symbol_counts(
- const Symbol_table*, size_t*, size_t*) const
-{
- gold_unreachable();
+ const Symbol_table*,
+ size_t* defined,
+ size_t* used) const
+{
+ *defined = this->defined_count_;
+ size_t count = 0;
+ for (typename Symbols::const_iterator p = this->symbols_.begin();
+ p != this->symbols_.end();
+ ++p)
+ if (*p != NULL
+ && (*p)->source() == Symbol::FROM_OBJECT
+ && (*p)->object() == this
+ && (*p)->is_defined()
+ && (*p)->dynsym_index() != -1U)
+ ++count;
+ *used = count;
}
// Allocate an incremental object of the appropriate size and endianness.
diff --git a/binutils-2.22/gold/incremental.h b/binutils-2.22/gold/incremental.h
index e6732df..20ae772 100644
--- a/binutils-2.22/gold/incremental.h
+++ b/binutils-2.22/gold/incremental.h
@@ -1,6 +1,6 @@
// inremental.h -- incremental linking support for gold -*- C++ -*-
-// Copyright 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
// Written by Mikolaj Zalewski <mikolajz@google.com>.
// This file is part of gold.
@@ -758,6 +758,23 @@ class Incremental_inputs_reader
typedef elfcpp::Swap<64, big_endian> Swap64;
public:
+ // Size of the .gnu_incremental_inputs header.
+ // (3 x 4-byte fields, plus 4 bytes padding.)
+ static const unsigned int header_size = 16;
+ // Size of an input file entry.
+ // (2 x 4-byte fields, 1 x 12-byte field, 2 x 2-byte fields.)
+ static const unsigned int input_entry_size = 24;
+ // Size of the first part of the supplemental info block for
+ // relocatable objects and archive members.
+ // (7 x 4-byte fields, plus 4 bytes padding.)
+ static const unsigned int object_info_size = 32;
+ // Size of an input section entry.
+ // (2 x 4-byte fields, 2 x address-sized fields.)
+ static const unsigned int input_section_entry_size = 8 + 2 * size / 8;
+ // Size of a global symbol entry in the supplemental info block.
+ // (5 x 4-byte fields.)
+ static const unsigned int global_sym_entry_size = 20;
+
Incremental_inputs_reader()
: p_(NULL), strtab_(NULL, 0), input_file_count_(0)
{ }
@@ -788,6 +805,14 @@ class Incremental_inputs_reader
// Reader class for an input file entry and its supplemental info.
class Incremental_input_entry_reader
{
+ private:
+ static const unsigned int object_info_size =
+ Incremental_inputs_reader<size, big_endian>::object_info_size;
+ static const unsigned int input_section_entry_size =
+ Incremental_inputs_reader<size, big_endian>::input_section_entry_size;
+ static const unsigned int global_sym_entry_size =
+ Incremental_inputs_reader<size, big_endian>::global_sym_entry_size;
+
public:
Incremental_input_entry_reader(const Incremental_inputs_reader* inputs,
unsigned int offset)
@@ -866,9 +891,10 @@ class Incremental_inputs_reader
|| this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
unsigned int section_count = this->get_input_section_count();
- return (this->info_offset_ + 28
- + section_count * input_section_entry_size
- + symndx * 20);
+ return (this->info_offset_
+ + this->object_info_size
+ + section_count * this->input_section_entry_size
+ + symndx * this->global_sym_entry_size);
}
// Return the global symbol count -- for objects & shared libraries only.
@@ -1001,8 +1027,9 @@ class Incremental_inputs_reader
{
Input_section_info info;
const unsigned char* p = (this->inputs_->p_
- + this->info_offset_ + 28
- + n * input_section_entry_size);
+ + this->info_offset_
+ + this->object_info_size
+ + n * this->input_section_entry_size);
unsigned int name_offset = Swap32::readval(p);
info.name = this->inputs_->get_string(name_offset);
info.output_shndx = Swap32::readval(p + 4);
@@ -1019,9 +1046,10 @@ class Incremental_inputs_reader
|| this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
unsigned int section_count = this->get_input_section_count();
const unsigned char* p = (this->inputs_->p_
- + this->info_offset_ + 28
- + section_count * input_section_entry_size
- + n * 20);
+ + this->info_offset_
+ + this->object_info_size
+ + section_count * this->input_section_entry_size
+ + n * this->global_sym_entry_size);
return Incremental_global_symbol_reader<big_endian>(p);
}
@@ -1032,9 +1060,10 @@ class Incremental_inputs_reader
unsigned int section_count = this->get_input_section_count();
unsigned int symbol_count = this->get_global_symbol_count();
const unsigned char* p = (this->inputs_->p_
- + this->info_offset_ + 28
- + section_count * input_section_entry_size
- + symbol_count * 20
+ + this->info_offset_
+ + this->object_info_size
+ + section_count * this->input_section_entry_size
+ + symbol_count * this->global_sym_entry_size
+ n * 4);
unsigned int name_offset = Swap32::readval(p);
return this->inputs_->get_string(name_offset);
@@ -1072,8 +1101,6 @@ class Incremental_inputs_reader
}
private:
- // Size of an input section entry.
- static const unsigned int input_section_entry_size = 8 + 2 * size / 8;
// The reader instance for the containing section.
const Incremental_inputs_reader* inputs_;
// The flags, including the type of input file.
@@ -1089,14 +1116,14 @@ class Incremental_inputs_reader
input_file_offset(unsigned int n) const
{
gold_assert(n < this->input_file_count_);
- return 16 + n * 24;
+ return this->header_size + n * this->input_entry_size;
}
// Return the index of an input file entry given its OFFSET.
unsigned int
input_file_index(unsigned int offset) const
{
- int n = (offset - 16) / 24;
+ int n = ((offset - this->header_size) / this->input_entry_size);
gold_assert(input_file_offset(n) == offset);
return n;
}
@@ -1110,7 +1137,8 @@ class Incremental_inputs_reader
Incremental_input_entry_reader
input_file_at_offset(unsigned int offset) const
{
- gold_assert(offset < 16 + this->input_file_count_ * 24);
+ gold_assert(offset < (this->header_size
+ + this->input_file_count_ * this->input_entry_size));
return Incremental_input_entry_reader(this, offset);
}
@@ -1880,8 +1908,9 @@ class Sized_relobj_incr : public Sized_relobj<size, big_endian>
do_section_name(unsigned int shndx);
// Return a view of the contents of a section.
- Object::Location
- do_section_contents(unsigned int shndx);
+ const unsigned char*
+ do_section_contents(unsigned int shndx, section_size_type* plen,
+ bool cache);
// Return section flags.
uint64_t
@@ -1924,6 +1953,15 @@ class Sized_relobj_incr : public Sized_relobj<size, big_endian>
do_get_global_symbols() const
{ return &this->symbols_; }
+ // Return the value of a local symbol.
+ uint64_t
+ do_local_symbol_value(unsigned int, uint64_t) const
+ { gold_unreachable(); }
+
+ unsigned int
+ do_local_plt_offset(unsigned int) const
+ { gold_unreachable(); }
+
// Return the number of local symbols.
unsigned int
do_local_symbol_count() const
@@ -1996,6 +2034,8 @@ class Sized_relobj_incr : public Sized_relobj<size, big_endian>
unsigned int local_dynsym_offset_;
// The entries in the symbol table for the external symbols.
Symbols symbols_;
+ // Number of symbols defined in object file itself.
+ size_t defined_count_;
// The offset of the first incremental relocation for this object.
unsigned int incr_reloc_offset_;
// The number of incremental relocations for this object.
@@ -2075,8 +2115,9 @@ class Sized_incr_dynobj : public Dynobj
do_section_name(unsigned int shndx);
// Return a view of the contents of a section.
- Object::Location
- do_section_contents(unsigned int shndx);
+ const unsigned char*
+ do_section_contents(unsigned int shndx, section_size_type* plen,
+ bool cache);
// Return section flags.
uint64_t
@@ -2127,6 +2168,8 @@ class Sized_incr_dynobj : public Dynobj
Input_entry_reader input_reader_;
// The entries in the symbol table for the external symbols.
Symbols symbols_;
+ // Number of symbols defined in object file itself.
+ size_t defined_count_;
};
// Allocate an incremental object of the appropriate size and endianness.
diff --git a/binutils-2.22/gold/int_encoding.cc b/binutils-2.22/gold/int_encoding.cc
index 6d635ac..7887477 100644
--- a/binutils-2.22/gold/int_encoding.cc
+++ b/binutils-2.22/gold/int_encoding.cc
@@ -32,19 +32,20 @@ namespace gold {
// Read an unsigned LEB128 number. Each byte contains 7 bits of
// information, plus one bit saying whether the number continues or
-// not.
+// not. BYTE contains the first byte of the number, and is guaranteed
+// to have the continuation bit set.
uint64_t
-read_unsigned_LEB_128(const unsigned char* buffer, size_t* len)
+read_unsigned_LEB_128_x(const unsigned char* buffer, size_t* len,
+ unsigned char byte)
{
- uint64_t result = 0;
- size_t num_read = 0;
- unsigned int shift = 0;
- unsigned char byte;
+ uint64_t result = static_cast<uint64_t>(byte & 0x7f);
+ size_t num_read = 1;
+ unsigned int shift = 7;
do
{
- if (num_read >= 64 / 7)
+ if (num_read > 64 / 7 + 1)
{
gold_warning(_("Unusually large LEB128 decoded, "
"debug information may be corrupted"));
@@ -64,18 +65,20 @@ read_unsigned_LEB_128(const unsigned char* buffer, size_t* len)
// Read a signed LEB128 number. These are like regular LEB128
// numbers, except the last byte may have a sign bit set.
+// BYTE contains the first byte of the number, and is guaranteed
+// to have the continuation bit set.
int64_t
-read_signed_LEB_128(const unsigned char* buffer, size_t* len)
+read_signed_LEB_128_x(const unsigned char* buffer, size_t* len,
+ unsigned char byte)
{
- int64_t result = 0;
- int shift = 0;
- size_t num_read = 0;
- unsigned char byte;
+ int64_t result = static_cast<uint64_t>(byte & 0x7f);
+ int shift = 7;
+ size_t num_read = 1;
do
{
- if (num_read >= 64 / 7)
+ if (num_read > 64 / 7 + 1)
{
gold_warning(_("Unusually large LEB128 decoded, "
"debug information may be corrupted"));
diff --git a/binutils-2.22/gold/int_encoding.h b/binutils-2.22/gold/int_encoding.h
index 6485a93..467d224 100644
--- a/binutils-2.22/gold/int_encoding.h
+++ b/binutils-2.22/gold/int_encoding.h
@@ -38,16 +38,48 @@ namespace gold
//
// Read a ULEB 128 encoded integer from BUFFER. Return the length of the
-// encoded integer at the location PLEN.
+// encoded integer at the location PLEN. The common case of a single-byte
+// value is handled inline, and multi-byte values are processed by the _x
+// routine, where BYTE is the first byte of the value.
uint64_t
-read_unsigned_LEB_128(const unsigned char* buffer, size_t* plen);
+read_unsigned_LEB_128_x(const unsigned char* buffer, size_t* plen,
+ unsigned char byte);
+
+inline uint64_t
+read_unsigned_LEB_128(const unsigned char* buffer, size_t* plen)
+{
+ unsigned char byte = *buffer++;
+
+ if ((byte & 0x80) != 0)
+ return read_unsigned_LEB_128_x(buffer, plen, byte);
+
+ *plen = 1;
+ return static_cast<uint64_t>(byte);
+}
// Read an SLEB 128 encoded integer from BUFFER. Return the length of the
-// encoded integer at the location PLEN.
+// encoded integer at the location PLEN. The common case of a single-byte
+// value is handled inline, and multi-byte values are processed by the _x
+// routine, where BYTE is the first byte of the value.
int64_t
-read_signed_LEB_128(const unsigned char* buffer, size_t* plen);
+read_signed_LEB_128_x(const unsigned char* buffer, size_t* plen,
+ unsigned char byte);
+
+inline int64_t
+read_signed_LEB_128(const unsigned char* buffer, size_t* plen)
+{
+ unsigned char byte = *buffer++;
+
+ if ((byte & 0x80) != 0)
+ return read_signed_LEB_128_x(buffer, plen, byte);
+
+ *plen = 1;
+ if (byte & 0x40)
+ return -(static_cast<int64_t>(1) << 7) | static_cast<int64_t>(byte);
+ return static_cast<int64_t>(byte);
+}
// Write a ULEB 128 encoded VALUE to BUFFER.
diff --git a/binutils-2.22/gold/layout.cc b/binutils-2.22/gold/layout.cc
index 1c32bcf..ad667ab 100644
--- a/binutils-2.22/gold/layout.cc
+++ b/binutils-2.22/gold/layout.cc
@@ -1,6 +1,7 @@
// layout.cc -- lay out output file sections for gold
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -44,6 +45,7 @@
#include "symtab.h"
#include "dynobj.h"
#include "ehframe.h"
+#include "gdb-index.h"
#include "compressed_output.h"
#include "reduced_debug_output.h"
#include "object.h"
@@ -154,9 +156,9 @@ off_t
Free_list::allocate(off_t len, uint64_t align, off_t minoff)
{
gold_debug(DEBUG_INCREMENTAL,
- "Free_list::allocate(%08lx, %d, %08lx)",
- static_cast<long>(len), static_cast<int>(align),
- static_cast<long>(minoff));
+ "Free_list::allocate(%08lx, %d, %08lx)",
+ static_cast<long>(len), static_cast<int>(align),
+ static_cast<long>(minoff));
if (len == 0)
return align_address(minoff, align);
@@ -221,17 +223,17 @@ void
Free_list::print_stats()
{
fprintf(stderr, _("%s: total free lists: %u\n"),
- program_name, Free_list::num_lists);
+ program_name, Free_list::num_lists);
fprintf(stderr, _("%s: total free list nodes: %u\n"),
- program_name, Free_list::num_nodes);
+ program_name, Free_list::num_nodes);
fprintf(stderr, _("%s: calls to Free_list::remove: %u\n"),
- program_name, Free_list::num_removes);
+ program_name, Free_list::num_removes);
fprintf(stderr, _("%s: nodes visited: %u\n"),
- program_name, Free_list::num_remove_visits);
+ program_name, Free_list::num_remove_visits);
fprintf(stderr, _("%s: calls to Free_list::allocate: %u\n"),
- program_name, Free_list::num_allocates);
+ program_name, Free_list::num_allocates);
fprintf(stderr, _("%s: nodes visited: %u\n"),
- program_name, Free_list::num_allocate_visits);
+ program_name, Free_list::num_allocate_visits);
}
// Layout::Relaxation_debug_check methods.
@@ -255,7 +257,7 @@ Layout::Relaxation_debug_check::check_output_data_for_reset_values(
++p)
gold_assert((*p)->address_and_file_offset_have_reset_values());
}
-
+
// Save information of SECTIONS for checking later.
void
@@ -318,7 +320,7 @@ Layout_task_runner::run(Workqueue* workqueue, const Task* task)
Layout* layout = this->layout_;
off_t file_size = layout->finalize(this->input_objects_,
this->symtab_,
- this->target_,
+ this->target_,
task);
// Now we know the final size of the output file and we know where
@@ -348,8 +350,8 @@ Layout_task_runner::run(Workqueue* workqueue, const Task* task)
// incremental information from the file before (possibly)
// overwriting it.
if (parameters->incremental_update())
- layout->incremental_base()->apply_incremental_relocs(this->symtab_,
- this->layout_,
+ layout->incremental_base()->apply_incremental_relocs(this->symtab_,
+ this->layout_,
of);
of->resize(file_size);
@@ -390,6 +392,7 @@ Layout::Layout(int number_of_input_files, Script_options* script_options)
eh_frame_data_(NULL),
added_eh_frame_data_(false),
eh_frame_hdr_section_(NULL),
+ gdb_index_data_(NULL),
build_id_note_(NULL),
debug_abbrev_(NULL),
debug_info_(NULL),
@@ -410,6 +413,7 @@ Layout::Layout(int number_of_input_files, Script_options* script_options)
script_output_section_data_list_(),
segment_states_(NULL),
relaxation_debug_check_(NULL),
+ section_order_map_(),
input_section_position_(),
input_section_glob_(),
incremental_base_(NULL),
@@ -449,56 +453,98 @@ Layout::Hash_key::operator()(const Layout::Key& k) const
return k.first + k.second.first + k.second.second;
}
-// Returns whether the given section is in the list of
-// debug-sections-used-by-some-version-of-gdb. Currently,
-// we've checked versions of gdb up to and including 6.7.1.
+// These are the debug sections that are actually used by gdb.
+// Currently, we've checked versions of gdb up to and including 7.4.
+// We only check the part of the name that follows ".debug_" or
+// ".zdebug_".
static const char* gdb_sections[] =
-{ ".debug_abbrev",
- // ".debug_aranges", // not used by gdb as of 6.7.1
- ".debug_frame",
- ".debug_info",
- ".debug_types",
- ".debug_line",
- ".debug_loc",
- ".debug_macinfo",
- // ".debug_pubnames", // not used by gdb as of 6.7.1
- ".debug_ranges",
- ".debug_str",
+{
+ "abbrev",
+ "addr", // Fission extension
+ // "aranges", // not used by gdb as of 7.4
+ "frame",
+ "info",
+ "types",
+ "line",
+ "loc",
+ "macinfo",
+ "macro",
+ // "pubnames", // not used by gdb as of 7.4
+ // "pubtypes", // not used by gdb as of 7.4
+ "ranges",
+ "str",
};
+// This is the minimum set of sections needed for line numbers.
+
static const char* lines_only_debug_sections[] =
-{ ".debug_abbrev",
- // ".debug_aranges", // not used by gdb as of 6.7.1
- // ".debug_frame",
- ".debug_info",
- // ".debug_types",
- ".debug_line",
- // ".debug_loc",
- // ".debug_macinfo",
- // ".debug_pubnames", // not used by gdb as of 6.7.1
- // ".debug_ranges",
- ".debug_str",
+{
+ "abbrev",
+ // "addr", // Fission extension
+ // "aranges", // not used by gdb as of 7.4
+ // "frame",
+ "info",
+ // "types",
+ "line",
+ // "loc",
+ // "macinfo",
+ // "macro",
+ // "pubnames", // not used by gdb as of 7.4
+ // "pubtypes", // not used by gdb as of 7.4
+ // "ranges",
+ "str",
};
+// These sections are the DWARF fast-lookup tables, and are not needed
+// when building a .gdb_index section.
+
+static const char* gdb_fast_lookup_sections[] =
+{
+ "aranges",
+ "pubnames",
+ "pubtypes",
+};
+
+// Returns whether the given debug section is in the list of
+// debug-sections-used-by-some-version-of-gdb. SUFFIX is the
+// portion of the name following ".debug_" or ".zdebug_".
+
static inline bool
-is_gdb_debug_section(const char* str)
+is_gdb_debug_section(const char* suffix)
{
// We can do this faster: binary search or a hashtable. But why bother?
for (size_t i = 0; i < sizeof(gdb_sections)/sizeof(*gdb_sections); ++i)
- if (strcmp(str, gdb_sections[i]) == 0)
+ if (strcmp(suffix, gdb_sections[i]) == 0)
return true;
return false;
}
+// Returns whether the given section is needed for lines-only debugging.
+
static inline bool
-is_lines_only_debug_section(const char* str)
+is_lines_only_debug_section(const char* suffix)
{
// We can do this faster: binary search or a hashtable. But why bother?
for (size_t i = 0;
i < sizeof(lines_only_debug_sections)/sizeof(*lines_only_debug_sections);
++i)
- if (strcmp(str, lines_only_debug_sections[i]) == 0)
+ if (strcmp(suffix, lines_only_debug_sections[i]) == 0)
+ return true;
+ return false;
+}
+
+// Returns whether the given section is a fast-lookup section that
+// will not be needed when building a .gdb_index section.
+
+static inline bool
+is_gdb_fast_lookup_section(const char* suffix)
+{
+ // We can do this faster: binary search or a hashtable. But why bother?
+ for (size_t i = 0;
+ i < sizeof(gdb_fast_lookup_sections)/sizeof(*gdb_fast_lookup_sections);
+ ++i)
+ if (strcmp(suffix, gdb_fast_lookup_sections[i]) == 0)
return true;
return false;
}
@@ -575,26 +621,44 @@ Layout::include_section(Sized_relobj_file<size, big_endian>*, const char* name,
&& (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
{
// Debugging sections can only be recognized by name.
- if (is_prefix_of(".debug", name)
- && !is_lines_only_debug_section(name))
+ if (is_prefix_of(".debug_", name)
+ && !is_lines_only_debug_section(name + 7))
+ return false;
+ if (is_prefix_of(".zdebug_", name)
+ && !is_lines_only_debug_section(name + 8))
return false;
}
if (parameters->options().strip_debug_gdb()
&& (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
{
// Debugging sections can only be recognized by name.
- if (is_prefix_of(".debug", name)
- && !is_gdb_debug_section(name))
+ if (is_prefix_of(".debug_", name)
+ && !is_gdb_debug_section(name + 7))
+ return false;
+ if (is_prefix_of(".zdebug_", name)
+ && !is_gdb_debug_section(name + 8))
+ return false;
+ }
+ if (parameters->options().gdb_index()
+ && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
+ {
+ // When building .gdb_index, we can strip .debug_pubnames,
+ // .debug_pubtypes, and .debug_aranges sections.
+ if (is_prefix_of(".debug_", name)
+ && is_gdb_fast_lookup_section(name + 7))
+ return false;
+ if (is_prefix_of(".zdebug_", name)
+ && is_gdb_fast_lookup_section(name + 8))
return false;
}
if (parameters->options().strip_lto_sections()
- && !parameters->options().relocatable()
- && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
- {
- // Ignore LTO sections containing intermediate code.
- if (is_prefix_of(".gnu.lto_", name))
- return false;
- }
+ && !parameters->options().relocatable()
+ && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
+ {
+ // Ignore LTO sections containing intermediate code.
+ if (is_prefix_of(".gnu.lto_", name))
+ return false;
+ }
// The GNU linker strips .gnu_debuglink sections, so we do too.
// This is a feature used to keep debugging information in
// separate files.
@@ -710,27 +774,27 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key,
if (lookup_type == elfcpp::SHT_PROGBITS)
{
- if (flags == 0)
- {
- Output_section* same_name = this->find_output_section(name);
- if (same_name != NULL
- && (same_name->type() == elfcpp::SHT_PROGBITS
+ if (flags == 0)
+ {
+ Output_section* same_name = this->find_output_section(name);
+ if (same_name != NULL
+ && (same_name->type() == elfcpp::SHT_PROGBITS
|| same_name->type() == elfcpp::SHT_INIT_ARRAY
|| same_name->type() == elfcpp::SHT_FINI_ARRAY
|| same_name->type() == elfcpp::SHT_PREINIT_ARRAY)
- && (same_name->flags() & elfcpp::SHF_TLS) == 0)
- os = same_name;
- }
- else if ((flags & elfcpp::SHF_TLS) == 0)
- {
- elfcpp::Elf_Xword zero_flags = 0;
- const Key zero_key(name_key, std::make_pair(lookup_type,
+ && (same_name->flags() & elfcpp::SHF_TLS) == 0)
+ os = same_name;
+ }
+ else if ((flags & elfcpp::SHF_TLS) == 0)
+ {
+ elfcpp::Elf_Xword zero_flags = 0;
+ const Key zero_key(name_key, std::make_pair(lookup_type,
zero_flags));
- Section_name_map::iterator p =
- this->section_name_map_.find(zero_key);
- if (p != this->section_name_map_.end())
+ Section_name_map::iterator p =
+ this->section_name_map_.find(zero_key);
+ if (p != this->section_name_map_.end())
os = p->second;
- }
+ }
}
if (os == NULL)
@@ -904,6 +968,13 @@ Layout::init_fixed_output_section(const char* name,
if (!can_incremental_update(sh_type))
return NULL;
+ // If we're generating a .gdb_index section, we need to regenerate
+ // it from scratch.
+ if (parameters->options().gdb_index()
+ && sh_type == elfcpp::SHT_PROGBITS
+ && strcmp(name, ".gdb_index") == 0)
+ return NULL;
+
typename elfcpp::Elf_types<size>::Elf_Addr sh_addr = shdr.get_sh_addr();
typename elfcpp::Elf_types<size>::Elf_Off sh_offset = shdr.get_sh_offset();
typename elfcpp::Elf_types<size>::Elf_WXword sh_size = shdr.get_sh_size();
@@ -915,7 +986,7 @@ Layout::init_fixed_output_section(const char* name,
Stringpool::Key name_key;
name = this->namepool_.add(name, true, &name_key);
Output_section* os = this->get_output_section(name, name_key, sh_type,
- sh_flags, ORDER_INVALID, false);
+ sh_flags, ORDER_INVALID, false);
os->set_fixed_layout(sh_addr, sh_offset, sh_size, sh_addralign);
if (sh_type != elfcpp::SHT_NOBITS)
this->free_list_.remove(sh_offset, sh_offset + sh_size);
@@ -1291,6 +1362,38 @@ Layout::add_eh_frame_for_plt(Output_data* plt, const unsigned char* cie_data,
}
}
+// Scan a .debug_info or .debug_types section, and add summary
+// information to the .gdb_index section.
+
+template<int size, bool big_endian>
+void
+Layout::add_to_gdb_index(bool is_type_unit,
+ Sized_relobj<size, big_endian>* object,
+ const unsigned char* symbols,
+ off_t symbols_size,
+ unsigned int shndx,
+ unsigned int reloc_shndx,
+ unsigned int reloc_type)
+{
+ if (this->gdb_index_data_ == NULL)
+ {
+ Output_section* os = this->choose_output_section(NULL, ".gdb_index",
+ elfcpp::SHT_PROGBITS, 0,
+ false, ORDER_INVALID,
+ false);
+ if (os == NULL)
+ return;
+
+ this->gdb_index_data_ = new Gdb_index(os);
+ os->add_output_section_data(this->gdb_index_data_);
+ os->set_after_input_sections();
+ }
+
+ this->gdb_index_data_->scan_debug_info(is_type_unit, object, symbols,
+ symbols_size, shndx, reloc_shndx,
+ reloc_type);
+}
+
// Add POSD to an output section using NAME, TYPE, and FLAGS. Return
// the output section.
@@ -1337,22 +1440,22 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
os = new Output_compressed_section(&parameters->options(), name, type,
flags);
else if ((flags & elfcpp::SHF_ALLOC) == 0
- && parameters->options().strip_debug_non_line()
- && strcmp(".debug_abbrev", name) == 0)
+ && parameters->options().strip_debug_non_line()
+ && strcmp(".debug_abbrev", name) == 0)
{
os = this->debug_abbrev_ = new Output_reduced_debug_abbrev_section(
- name, type, flags);
+ name, type, flags);
if (this->debug_info_)
- this->debug_info_->set_abbreviations(this->debug_abbrev_);
+ this->debug_info_->set_abbreviations(this->debug_abbrev_);
}
else if ((flags & elfcpp::SHF_ALLOC) == 0
- && parameters->options().strip_debug_non_line()
- && strcmp(".debug_info", name) == 0)
+ && parameters->options().strip_debug_non_line()
+ && strcmp(".debug_info", name) == 0)
{
os = this->debug_info_ = new Output_reduced_debug_info_section(
- name, type, flags);
+ name, type, flags);
if (this->debug_abbrev_)
- this->debug_info_->set_abbreviations(this->debug_abbrev_);
+ this->debug_info_->set_abbreviations(this->debug_abbrev_);
}
else
{
@@ -1378,25 +1481,29 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
bool is_relro_local = false;
if (!this->script_options_->saw_sections_clause()
&& parameters->options().relro()
- && type == elfcpp::SHT_PROGBITS
&& (flags & elfcpp::SHF_ALLOC) != 0
&& (flags & elfcpp::SHF_WRITE) != 0)
{
- if (strcmp(name, ".data.rel.ro") == 0)
- is_relro = true;
- else if (strcmp(name, ".data.rel.ro.local") == 0)
+ if (type == elfcpp::SHT_PROGBITS)
{
- is_relro = true;
- is_relro_local = true;
+ if ((flags & elfcpp::SHF_TLS) != 0)
+ is_relro = true;
+ else if (strcmp(name, ".data.rel.ro") == 0)
+ is_relro = true;
+ else if (strcmp(name, ".data.rel.ro.local") == 0)
+ {
+ is_relro = true;
+ is_relro_local = true;
+ }
+ else if (strcmp(name, ".ctors") == 0
+ || strcmp(name, ".dtors") == 0
+ || strcmp(name, ".jcr") == 0)
+ is_relro = true;
}
else if (type == elfcpp::SHT_INIT_ARRAY
|| type == elfcpp::SHT_FINI_ARRAY
|| type == elfcpp::SHT_PREINIT_ARRAY)
is_relro = true;
- else if (strcmp(name, ".ctors") == 0
- || strcmp(name, ".dtors") == 0
- || strcmp(name, ".jcr") == 0)
- is_relro = true;
}
if (is_relro)
@@ -1453,18 +1560,18 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
// a minimum size, so we must prevent allocations from the
// free list that leave a hole smaller than the minimum.
if (strcmp(name, ".debug_info") == 0)
- os->set_free_space_fill(new Output_fill_debug_info(false));
+ os->set_free_space_fill(new Output_fill_debug_info(false));
else if (strcmp(name, ".debug_types") == 0)
- os->set_free_space_fill(new Output_fill_debug_info(true));
+ os->set_free_space_fill(new Output_fill_debug_info(true));
else if (strcmp(name, ".debug_line") == 0)
- os->set_free_space_fill(new Output_fill_debug_line());
+ os->set_free_space_fill(new Output_fill_debug_line());
}
// If we have already attached the sections to segments, then we
// need to attach this one now. This happens for sections created
// directly by the linker.
if (this->sections_are_attached_)
- this->attach_section_to_segment(os);
+ this->attach_section_to_segment(&parameters->target(), os);
return os;
}
@@ -1541,12 +1648,12 @@ Layout::default_section_order(Output_section* os, bool is_relro_local)
// seen all the input sections.
void
-Layout::attach_sections_to_segments()
+Layout::attach_sections_to_segments(const Target* target)
{
for (Section_list::iterator p = this->section_list_.begin();
p != this->section_list_.end();
++p)
- this->attach_section_to_segment(*p);
+ this->attach_section_to_segment(target, *p);
this->sections_are_attached_ = true;
}
@@ -1554,18 +1661,19 @@ Layout::attach_sections_to_segments()
// Attach an output section to a segment.
void
-Layout::attach_section_to_segment(Output_section* os)
+Layout::attach_section_to_segment(const Target* target, Output_section* os)
{
if ((os->flags() & elfcpp::SHF_ALLOC) == 0)
this->unattached_section_list_.push_back(os);
else
- this->attach_allocated_section_to_segment(os);
+ this->attach_allocated_section_to_segment(target, os);
}
// Attach an allocated output section to a segment.
void
-Layout::attach_allocated_section_to_segment(Output_section* os)
+Layout::attach_allocated_section_to_segment(const Target* target,
+ Output_section* os)
{
elfcpp::Elf_Xword flags = os->flags();
gold_assert((flags & elfcpp::SHF_ALLOC) != 0);
@@ -1605,9 +1713,9 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
if (!parameters->options().omagic()
&& ((*p)->flags() & elfcpp::PF_W) != (seg_flags & elfcpp::PF_W))
continue;
- if (parameters->options().rosegment()
- && ((*p)->flags() & elfcpp::PF_X) != (seg_flags & elfcpp::PF_X))
- continue;
+ if ((target->isolate_execinstr() || parameters->options().rosegment())
+ && ((*p)->flags() & elfcpp::PF_X) != (seg_flags & elfcpp::PF_X))
+ continue;
// If -Tbss was specified, we need to separate the data and BSS
// segments.
if (parameters->options().user_set_Tbss())
@@ -1637,7 +1745,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
if (p == this->segment_list_.end())
{
Output_segment* oseg = this->make_output_segment(elfcpp::PT_LOAD,
- seg_flags);
+ seg_flags);
if (os->is_large_data_section())
oseg->set_is_large_data_segment();
oseg->add_output_section_to_load(this, os, seg_flags);
@@ -1651,24 +1759,24 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
{
// See if we already have an equivalent PT_NOTE segment.
for (p = this->segment_list_.begin();
- p != segment_list_.end();
- ++p)
- {
- if ((*p)->type() == elfcpp::PT_NOTE
- && (((*p)->flags() & elfcpp::PF_W)
- == (seg_flags & elfcpp::PF_W)))
- {
- (*p)->add_output_section_to_nonload(os, seg_flags);
- break;
- }
- }
+ p != segment_list_.end();
+ ++p)
+ {
+ if ((*p)->type() == elfcpp::PT_NOTE
+ && (((*p)->flags() & elfcpp::PF_W)
+ == (seg_flags & elfcpp::PF_W)))
+ {
+ (*p)->add_output_section_to_nonload(os, seg_flags);
+ break;
+ }
+ }
if (p == this->segment_list_.end())
- {
- Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
- seg_flags);
- oseg->add_output_section_to_nonload(os, seg_flags);
- }
+ {
+ Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
+ seg_flags);
+ oseg->add_output_section_to_nonload(os, seg_flags);
+ }
}
// If we see a loadable SHF_TLS section, we create a PT_TLS
@@ -1839,9 +1947,9 @@ Layout::define_section_symbols(Symbol_table* symtab)
{
const std::string name_string(name);
const std::string start_name(cident_section_start_prefix
- + name_string);
+ + name_string);
const std::string stop_name(cident_section_stop_prefix
- + name_string);
+ + name_string);
symtab->define_in_output_data(start_name.c_str(),
NULL, // version
@@ -1907,7 +2015,7 @@ Layout::define_group_signatures(Symbol_table* symtab)
// necessary.
Output_segment*
-Layout::find_first_load_seg()
+Layout::find_first_load_seg(const Target* target)
{
Output_segment* best = NULL;
for (Segment_list::const_iterator p = this->segment_list_.begin();
@@ -1917,11 +2025,13 @@ Layout::find_first_load_seg()
if ((*p)->type() == elfcpp::PT_LOAD
&& ((*p)->flags() & elfcpp::PF_R) != 0
&& (parameters->options().omagic()
- || ((*p)->flags() & elfcpp::PF_W) == 0))
- {
- if (best == NULL || this->segment_precedes(*p, best))
- best = *p;
- }
+ || ((*p)->flags() & elfcpp::PF_W) == 0)
+ && (!target->isolate_execinstr()
+ || ((*p)->flags() & elfcpp::PF_X) == 0))
+ {
+ if (best == NULL || this->segment_precedes(*p, best))
+ best = *p;
+ }
}
if (best != NULL)
return best;
@@ -1979,10 +2089,10 @@ Layout::restore_segments(const Segment_states* segment_states)
this->relro_segment_ = segment;
++list_iter;
- }
+ }
else
{
- list_iter = this->segment_list_.erase(list_iter);
+ list_iter = this->segment_list_.erase(list_iter);
// This is a segment created during section layout. It should be
// safe to remove it since we should have removed all pointers to it.
delete segment;
@@ -2015,7 +2125,7 @@ Layout::clean_up_after_relaxation()
(*p)->reset_address_and_file_offset();
}
-
+
// Reset special output object address and file offsets.
for (Data_list::iterator p = this->special_output_list_.begin();
p != this->special_output_list_.end();
@@ -2029,7 +2139,7 @@ Layout::clean_up_after_relaxation()
p != this->script_output_section_data_list_.end();
++p)
delete *p;
- this->script_output_section_data_list_.clear();
+ this->script_output_section_data_list_.clear();
}
// Prepare for relaxation.
@@ -2052,7 +2162,7 @@ Layout::prepare_for_relaxation()
if (is_debugging_enabled(DEBUG_RELAXATION))
this->relaxation_debug_check_->check_output_data_for_reset_values(
- this->section_list_, this->special_output_list_);
+ this->section_list_, this->special_output_list_);
// Also enable recording of output section data from scripts.
this->record_output_section_data_from_script_ = true;
@@ -2061,7 +2171,7 @@ Layout::prepare_for_relaxation()
// Relaxation loop body: If target has no relaxation, this runs only once
// Otherwise, the target relaxation hook is called at the end of
// each iteration. If the hook returns true, it means re-layout of
-// section is required.
+// section is required.
//
// The number of segments created by a linking script without a PHDRS
// clause may be affected by section sizes and alignments. There is
@@ -2071,8 +2181,8 @@ Layout::prepare_for_relaxation()
// layout. In order to be able to restart the section layout, we keep
// a copy of the segment list right before the relaxation loop and use
// that to restore the segments.
-//
-// PASS is the current relaxation pass number.
+//
+// PASS is the current relaxation pass number.
// SYMTAB is a symbol table.
// PLOAD_SEG is the address of a pointer for the load segment.
// PHDR_SEG is a pointer to the PHDR segment.
@@ -2104,7 +2214,7 @@ Layout::relaxation_loop_body(
else if (parameters->options().relocatable())
load_seg = NULL;
else
- load_seg = this->find_first_load_seg();
+ load_seg = this->find_first_load_seg(target);
if (parameters->options().oformat_enum()
!= General_options::OBJECT_FORMAT_ELF)
@@ -2161,9 +2271,9 @@ Layout::relaxation_loop_body(
load_seg->add_initial_output_data(z);
}
if (load_seg != NULL)
- load_seg->add_initial_output_data(segment_headers);
+ load_seg->add_initial_output_data(segment_headers);
if (phdr_seg != NULL)
- phdr_seg->add_initial_output_data(segment_headers);
+ phdr_seg->add_initial_output_data(segment_headers);
}
// Lay out the file header.
@@ -2224,11 +2334,11 @@ Layout::find_section_order_index(const std::string& section_name)
++it)
{
if (fnmatch((*it).c_str(), section_name.c_str(), FNM_NOESCAPE) == 0)
- {
- map_it = this->input_section_position_.find(*it);
- gold_assert(map_it != this->input_section_position_.end());
- return map_it->second;
- }
+ {
+ map_it = this->input_section_position_.find(*it);
+ gold_assert(map_it != this->input_section_position_.end());
+ return map_it->second;
+ }
}
return 0;
}
@@ -2246,7 +2356,7 @@ Layout::read_layout_from_file()
in.open(filename);
if (!in)
gold_fatal(_("unable to open --section-ordering-file file %s: %s"),
- filename, strerror(errno));
+ filename, strerror(errno));
std::getline(in, line); // this chops off the trailing \n, if any
unsigned int position = 1;
@@ -2255,17 +2365,17 @@ Layout::read_layout_from_file()
while (in)
{
if (!line.empty() && line[line.length() - 1] == '\r') // Windows
- line.resize(line.length() - 1);
+ line.resize(line.length() - 1);
// Ignore comments, beginning with '#'
if (line[0] == '#')
- {
- std::getline(in, line);
- continue;
- }
+ {
+ std::getline(in, line);
+ continue;
+ }
this->input_section_position_[line] = position;
// Store all glob patterns in a vector.
if (is_wildcard_string(line.c_str()))
- this->input_section_glob_.push_back(line);
+ this->input_section_glob_.push_back(line);
position++;
std::getline(in, line);
}
@@ -2329,7 +2439,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
std::vector<Symbol*> dynamic_symbols;
unsigned int local_dynamic_count;
Versions versions(*this->script_options()->version_script_info(),
- &this->dynpool_);
+ &this->dynpool_);
this->create_dynamic_symtab(input_objects, symtab, &dynstr,
&local_dynamic_count, &dynamic_symbols,
&versions);
@@ -2340,7 +2450,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
if ((!parameters->options().shared()
|| parameters->options().dynamic_linker() != NULL)
&& this->interp_segment_ == NULL)
- this->create_interp(target);
+ this->create_interp(target);
// Finish the .dynamic section to hold the dynamic data, and put
// it in a PT_DYNAMIC segment.
@@ -2359,7 +2469,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
// after we call create_version_sections.
this->set_dynamic_symbol_size(symtab);
}
-
+
// Create segment headers.
Output_segment_headers* segment_headers =
(parameters->options().relocatable()
@@ -2378,7 +2488,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
// a linker script.
if (this->script_options_->saw_sections_clause())
this->place_orphan_sections_in_script();
-
+
Output_segment* load_seg;
off_t off;
unsigned int shndx;
@@ -2387,7 +2497,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
// Take a snapshot of the section layout as needed.
if (target->may_relax())
this->prepare_for_relaxation();
-
+
// Run the relaxation loop to lay out sections.
do
{
@@ -2399,6 +2509,16 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
while (target->may_relax()
&& target->relax(pass, input_objects, symtab, this, task));
+ // If there is a load segment that contains the file and program headers,
+ // provide a symbol __ehdr_start pointing there.
+ // A program can use this to examine itself robustly.
+ if (load_seg != NULL)
+ symtab->define_in_output_segment("__ehdr_start", NULL,
+ Symbol_table::PREDEFINED, load_seg, 0, 0,
+ elfcpp::STT_NOTYPE, elfcpp::STB_GLOBAL,
+ elfcpp::STV_DEFAULT, 0,
+ Symbol::SEGMENT_START, true);
+
// Set the file offsets of all the non-data sections we've seen so
// far which don't have to wait for the input sections. We need
// this in order to finalize local symbols in non-allocated
@@ -2829,8 +2949,8 @@ Layout::create_incremental_info_sections(Symbol_table* symtab)
const char* incremental_strtab_name =
this->namepool_.add(".gnu_incremental_strtab", false, NULL);
Output_section* incremental_strtab_os = this->make_output_section(incremental_strtab_name,
- elfcpp::SHT_STRTAB, 0,
- ORDER_INVALID, false);
+ elfcpp::SHT_STRTAB, 0,
+ ORDER_INVALID, false);
Output_data_strtab* strtab_data =
new Output_data_strtab(incr->get_stringpool());
incremental_strtab_os->add_output_section_data(strtab_data);
@@ -2975,8 +3095,9 @@ Layout::segment_precedes(const Output_segment* seg1,
// We shouldn't get here--we shouldn't create segments which we
// can't distinguish. Unless of course we are using a weird linker
- // script.
- gold_assert(this->script_options_->saw_phdrs_clause());
+ // script or overlapping --section-start options.
+ gold_assert(this->script_options_->saw_phdrs_clause()
+ || parameters->options().any_section_start());
return false;
}
@@ -3009,13 +3130,15 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
// Find the PT_LOAD segments, and set their addresses and offsets
// and their section's addresses and offsets.
- uint64_t addr;
+ uint64_t start_addr;
if (parameters->options().user_set_Ttext())
- addr = parameters->options().Ttext();
+ start_addr = parameters->options().Ttext();
else if (parameters->options().output_is_position_independent())
- addr = 0;
+ start_addr = 0;
else
- addr = target->default_text_segment_address();
+ start_addr = target->default_text_segment_address();
+
+ uint64_t addr = start_addr;
off_t off = 0;
// If LOAD_SEG is NULL, then the file header and segment headers
@@ -3040,15 +3163,39 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
const bool check_sections = parameters->options().check_sections();
Output_segment* last_load_segment = NULL;
+ unsigned int shndx_begin = *pshndx;
+ unsigned int shndx_load_seg = *pshndx;
+
for (Segment_list::iterator p = this->segment_list_.begin();
p != this->segment_list_.end();
++p)
{
if ((*p)->type() == elfcpp::PT_LOAD)
{
- if (load_seg != NULL && load_seg != *p)
- gold_unreachable();
- load_seg = NULL;
+ if (target->isolate_execinstr())
+ {
+ // When we hit the segment that should contain the
+ // file headers, reset the file offset so we place
+ // it and subsequent segments appropriately.
+ // We'll fix up the preceding segments below.
+ if (load_seg == *p)
+ {
+ if (off == 0)
+ load_seg = NULL;
+ else
+ {
+ off = 0;
+ shndx_load_seg = *pshndx;
+ }
+ }
+ }
+ else
+ {
+ // Verify that the file headers fall into the first segment.
+ if (load_seg != NULL && load_seg != *p)
+ gold_unreachable();
+ load_seg = NULL;
+ }
bool are_addresses_set = (*p)->are_addresses_set();
if (are_addresses_set)
@@ -3100,16 +3247,37 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
addr = align_address(addr, (*p)->maximum_alignment());
aligned_addr = addr;
- if ((addr & (abi_pagesize - 1)) != 0)
- addr = addr + abi_pagesize;
+ if (load_seg == *p)
+ {
+ // This is the segment that will contain the file
+ // headers, so its offset will have to be exactly zero.
+ gold_assert(orig_off == 0);
+
+ // If the target wants a fixed minimum distance from the
+ // text segment to the read-only segment, move up now.
+ uint64_t min_addr = start_addr + target->rosegment_gap();
+ if (addr < min_addr)
+ addr = min_addr;
+
+ // But this is not the first segment! To make its
+ // address congruent with its offset, that address better
+ // be aligned to the ABI-mandated page size.
+ addr = align_address(addr, abi_pagesize);
+ aligned_addr = addr;
+ }
+ else
+ {
+ if ((addr & (abi_pagesize - 1)) != 0)
+ addr = addr + abi_pagesize;
- off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
+ off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
+ }
}
if (!parameters->options().nmagic()
&& !parameters->options().omagic())
off = align_file_offset(off, addr, abi_pagesize);
- else if (load_seg == NULL)
+ else
{
// This is -N or -n with a section script which prevents
// us from using a load segment. We need to ensure that
@@ -3128,7 +3296,7 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
uint64_t new_addr = (*p)->set_section_addresses(this, false, addr,
&increase_relro,
&has_relro,
- &off, pshndx);
+ &off, pshndx);
// Now that we know the size of this segment, we may be able
// to save a page in memory, at the cost of wasting some
@@ -3167,7 +3335,7 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
new_addr = (*p)->set_section_addresses(this, true, addr,
&increase_relro,
&has_relro,
- &off, pshndx);
+ &off, pshndx);
}
}
@@ -3194,6 +3362,38 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg,
}
}
+ if (load_seg != NULL && target->isolate_execinstr())
+ {
+ // Process the early segments again, setting their file offsets
+ // so they land after the segments starting at LOAD_SEG.
+ off = align_file_offset(off, 0, target->abi_pagesize());
+
+ for (Segment_list::iterator p = this->segment_list_.begin();
+ *p != load_seg;
+ ++p)
+ {
+ if ((*p)->type() == elfcpp::PT_LOAD)
+ {
+ // We repeat the whole job of assigning addresses and
+ // offsets, but we really only want to change the offsets and
+ // must ensure that the addresses all come out the same as
+ // they did the first time through.
+ bool has_relro = false;
+ const uint64_t old_addr = (*p)->vaddr();
+ const uint64_t old_end = old_addr + (*p)->memsz();
+ uint64_t new_addr = (*p)->set_section_addresses(this, true,
+ old_addr,
+ &increase_relro,
+ &has_relro,
+ &off,
+ &shndx_begin);
+ gold_assert(new_addr == old_end);
+ }
+ }
+
+ gold_assert(shndx_begin == shndx_load_seg);
+ }
+
// Handle the non-PT_LOAD segments, setting their offsets from their
// section's offsets.
for (Segment_list::iterator p = this->segment_list_.begin();
@@ -3281,16 +3481,16 @@ Layout::set_section_offsets(off_t off, Layout::Section_offset_pass pass)
}
if (pass == BEFORE_INPUT_SECTIONS_PASS
- && (*p)->after_input_sections())
- continue;
+ && (*p)->after_input_sections())
+ continue;
else if (pass == POSTPROCESSING_SECTIONS_PASS
- && (!(*p)->after_input_sections()
- || (*p)->type() == elfcpp::SHT_STRTAB))
- continue;
+ && (!(*p)->after_input_sections()
+ || (*p)->type() == elfcpp::SHT_STRTAB))
+ continue;
else if (pass == STRTAB_AFTER_POSTPROCESSING_SECTIONS_PASS
- && (!(*p)->after_input_sections()
- || (*p)->type() != elfcpp::SHT_STRTAB))
- continue;
+ && (!(*p)->after_input_sections()
+ || (*p)->type() != elfcpp::SHT_STRTAB))
+ continue;
if (!parameters->incremental_update())
{
@@ -3307,7 +3507,7 @@ Layout::set_section_offsets(off_t off, Layout::Section_offset_pass pass)
if (off == -1)
{
if (is_debugging_enabled(DEBUG_INCREMENTAL))
- this->free_list_.dump();
+ this->free_list_.dump();
gold_assert((*p)->output_section() != NULL);
gold_fallback(_("out of patch space for section %s; "
"relink with --incremental-full"),
@@ -3332,7 +3532,7 @@ Layout::set_section_offsets(off_t off, Layout::Section_offset_pass pass)
off += (*p)->data_size();
if (off > maxoff)
- maxoff = off;
+ maxoff = off;
// At this point the name must be set.
if (pass != STRTAB_AFTER_POSTPROCESSING_SECTIONS_PASS)
@@ -3480,7 +3680,7 @@ Layout::create_symtab_sections(const Input_objects* input_objects,
++p)
{
unsigned int index = (*p)->finalize_local_symbols(local_symbol_index,
- off, symtab);
+ off, symtab);
off += (index - local_symbol_index) * symsize;
local_symbol_index = index;
}
@@ -3574,7 +3774,7 @@ Layout::create_symtab_sections(const Input_objects* input_objects,
else
{
symtab_off = this->allocate(off, align, *poff);
- if (off == -1)
+ if (off == -1)
gold_fallback(_("out of patch space for symbol table; "
"relink with --incremental-full"));
gold_debug(DEBUG_INCREMENTAL,
@@ -3677,7 +3877,7 @@ Layout::allocated_output_section_count() const
void
Layout::create_dynamic_symtab(const Input_objects* input_objects,
- Symbol_table* symtab,
+ Symbol_table* symtab,
Output_section** pdynstr,
unsigned int* plocal_dynamic_count,
std::vector<Symbol*>* pdynamic_symbols,
@@ -4256,45 +4456,45 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
{
case elfcpp::SHT_FINI_ARRAY:
odyn->add_section_address(elfcpp::DT_FINI_ARRAY, *p);
- odyn->add_section_size(elfcpp::DT_FINI_ARRAYSZ, *p);
+ odyn->add_section_size(elfcpp::DT_FINI_ARRAYSZ, *p);
break;
case elfcpp::SHT_INIT_ARRAY:
odyn->add_section_address(elfcpp::DT_INIT_ARRAY, *p);
- odyn->add_section_size(elfcpp::DT_INIT_ARRAYSZ, *p);
+ odyn->add_section_size(elfcpp::DT_INIT_ARRAYSZ, *p);
break;
case elfcpp::SHT_PREINIT_ARRAY:
odyn->add_section_address(elfcpp::DT_PREINIT_ARRAY, *p);
- odyn->add_section_size(elfcpp::DT_PREINIT_ARRAYSZ, *p);
+ odyn->add_section_size(elfcpp::DT_PREINIT_ARRAYSZ, *p);
break;
default:
break;
}
-
+
// Add a DT_RPATH entry if needed.
const General_options::Dir_list& rpath(parameters->options().rpath());
if (!rpath.empty())
{
std::string rpath_val;
for (General_options::Dir_list::const_iterator p = rpath.begin();
- p != rpath.end();
- ++p)
- {
- if (rpath_val.empty())
- rpath_val = p->name();
- else
- {
- // Eliminate duplicates.
- General_options::Dir_list::const_iterator q;
- for (q = rpath.begin(); q != p; ++q)
+ p != rpath.end();
+ ++p)
+ {
+ if (rpath_val.empty())
+ rpath_val = p->name();
+ else
+ {
+ // Eliminate duplicates.
+ General_options::Dir_list::const_iterator q;
+ for (q = rpath.begin(); q != p; ++q)
if (q->name() == p->name())
- break;
- if (q == p)
- {
- rpath_val += ':';
- rpath_val += p->name();
- }
- }
- }
+ break;
+ if (q == p)
+ {
+ rpath_val += ':';
+ rpath_val += p->name();
+ }
+ }
+ }
odyn->add_string(elfcpp::DT_RPATH, rpath_val);
if (parameters->options().enable_new_dtags())
@@ -4306,17 +4506,17 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
if (!this->script_options_->saw_sections_clause())
{
for (Segment_list::const_iterator p = this->segment_list_.begin();
- p != this->segment_list_.end();
- ++p)
- {
- if ((*p)->type() == elfcpp::PT_LOAD
+ p != this->segment_list_.end();
+ ++p)
+ {
+ if ((*p)->type() == elfcpp::PT_LOAD
&& ((*p)->flags() & elfcpp::PF_W) == 0
- && (*p)->has_dynamic_reloc())
- {
- have_textrel = true;
- break;
- }
- }
+ && (*p)->has_dynamic_reloc())
+ {
+ have_textrel = true;
+ break;
+ }
+ }
}
else
{
@@ -4325,17 +4525,17 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
// relocations. If those sections wind up in writable segments,
// then we have created an unnecessary DT_TEXTREL entry.
for (Section_list::const_iterator p = this->section_list_.begin();
- p != this->section_list_.end();
- ++p)
- {
- if (((*p)->flags() & elfcpp::SHF_ALLOC) != 0
- && ((*p)->flags() & elfcpp::SHF_WRITE) == 0
- && (*p)->has_dynamic_reloc())
- {
- have_textrel = true;
- break;
- }
- }
+ p != this->section_list_.end();
+ ++p)
+ {
+ if (((*p)->flags() & elfcpp::SHF_ALLOC) != 0
+ && ((*p)->flags() & elfcpp::SHF_WRITE) == 0
+ && (*p)->has_dynamic_reloc())
+ {
+ have_textrel = true;
+ break;
+ }
+ }
}
if (parameters->options().filter() != NULL)
@@ -4435,12 +4635,15 @@ Layout::set_dynamic_symbol_size(const Symbol_table* symtab)
// based on the GNU linker default ELF linker script.
#define MAPPING_INIT(f, t) { f, sizeof(f) - 1, t, sizeof(t) - 1 }
+#define MAPPING_INIT_EXACT(f, t) { f, 0, t, sizeof(t) - 1 }
const Layout::Section_name_mapping Layout::section_name_mapping[] =
{
MAPPING_INIT(".text.", ".text"),
MAPPING_INIT(".rodata.", ".rodata"),
- MAPPING_INIT(".data.rel.ro.local", ".data.rel.ro.local"),
- MAPPING_INIT(".data.rel.ro", ".data.rel.ro"),
+ MAPPING_INIT(".data.rel.ro.local.", ".data.rel.ro.local"),
+ MAPPING_INIT_EXACT(".data.rel.ro.local", ".data.rel.ro.local"),
+ MAPPING_INIT(".data.rel.ro.", ".data.rel.ro"),
+ MAPPING_INIT_EXACT(".data.rel.ro", ".data.rel.ro"),
MAPPING_INIT(".data.", ".data"),
MAPPING_INIT(".bss.", ".bss"),
MAPPING_INIT(".tdata.", ".tdata"),
@@ -4479,6 +4682,7 @@ const Layout::Section_name_mapping Layout::section_name_mapping[] =
MAPPING_INIT(".gnu.linkonce.armexidx.", ".ARM.exidx"),
};
#undef MAPPING_INIT
+#undef MAPPING_INIT_EXACT
const int Layout::section_name_mapping_count =
(sizeof(Layout::section_name_mapping)
@@ -4530,10 +4734,21 @@ Layout::output_section_name(const Relobj* relobj, const char* name,
const Section_name_mapping* psnm = section_name_mapping;
for (int i = 0; i < section_name_mapping_count; ++i, ++psnm)
{
- if (strncmp(name, psnm->from, psnm->fromlen) == 0)
+ if (psnm->fromlen > 0)
+ {
+ if (strncmp(name, psnm->from, psnm->fromlen) == 0)
+ {
+ *plen = psnm->tolen;
+ return psnm->to;
+ }
+ }
+ else
{
- *plen = psnm->tolen;
- return psnm->to;
+ if (strcmp(name, psnm->from) == 0)
+ {
+ *plen = psnm->tolen;
+ return psnm->to;
+ }
}
}
@@ -4607,7 +4822,7 @@ Layout::find_or_add_kept_section(const std::string& name,
unsigned int shndx,
bool is_comdat,
bool is_group_name,
- Kept_section** kept_section)
+ Kept_section** kept_section)
{
// It's normal to see a couple of entries here, for the x86 thunk
// sections. If we see more than a few, we're linking a C++
@@ -4646,12 +4861,12 @@ Layout::find_or_add_kept_section(const std::string& name,
// If the kept group is from a plugin object, and we're in the
// replacement phase, accept the new one as a replacement.
if (ins.first->second.object() == NULL
- && parameters->options().plugins()->in_replacement_phase())
- {
+ && parameters->options().plugins()->in_replacement_phase())
+ {
ins.first->second.set_object(object);
ins.first->second.set_shndx(shndx);
- return true;
- }
+ return true;
+ }
return false;
}
else if (is_group_name)
@@ -5293,4 +5508,52 @@ Layout::layout_eh_frame<64, true>(Sized_relobj_file<64, true>* object,
off_t* off);
#endif
+#ifdef HAVE_TARGET_32_LITTLE
+template
+void
+Layout::add_to_gdb_index(bool is_type_unit,
+ Sized_relobj<32, false>* object,
+ const unsigned char* symbols,
+ off_t symbols_size,
+ unsigned int shndx,
+ unsigned int reloc_shndx,
+ unsigned int reloc_type);
+#endif
+
+#ifdef HAVE_TARGET_32_BIG
+template
+void
+Layout::add_to_gdb_index(bool is_type_unit,
+ Sized_relobj<32, true>* object,
+ const unsigned char* symbols,
+ off_t symbols_size,
+ unsigned int shndx,
+ unsigned int reloc_shndx,
+ unsigned int reloc_type);
+#endif
+
+#ifdef HAVE_TARGET_64_LITTLE
+template
+void
+Layout::add_to_gdb_index(bool is_type_unit,
+ Sized_relobj<64, false>* object,
+ const unsigned char* symbols,
+ off_t symbols_size,
+ unsigned int shndx,
+ unsigned int reloc_shndx,
+ unsigned int reloc_type);
+#endif
+
+#ifdef HAVE_TARGET_64_BIG
+template
+void
+Layout::add_to_gdb_index(bool is_type_unit,
+ Sized_relobj<64, true>* object,
+ const unsigned char* symbols,
+ off_t symbols_size,
+ unsigned int shndx,
+ unsigned int reloc_shndx,
+ unsigned int reloc_type);
+#endif
+
} // End namespace gold.
diff --git a/binutils-2.22/gold/layout.h b/binutils-2.22/gold/layout.h
index 05cb50f..4643e32 100644
--- a/binutils-2.22/gold/layout.h
+++ b/binutils-2.22/gold/layout.h
@@ -1,6 +1,7 @@
// layout.h -- lay out output file sections for gold -*- C++ -*-
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -58,6 +59,7 @@ class Output_symtab_xindex;
class Output_reduced_debug_abbrev_section;
class Output_reduced_debug_info_section;
class Eh_frame;
+class Gdb_index;
class Target;
struct Timespec;
@@ -170,7 +172,7 @@ class Layout_task_runner : public Task_function_runner
Layout_task_runner(const General_options& options,
const Input_objects* input_objects,
Symbol_table* symtab,
- Target* target,
+ Target* target,
Layout* layout,
Mapfile* mapfile)
: options_(options), input_objects_(input_objects), symtab_(symtab),
@@ -522,6 +524,10 @@ class Layout
const char* name, const elfcpp::Shdr<size, big_endian>& shdr,
unsigned int reloc_shndx, unsigned int reloc_type, off_t* offset);
+ std::map<Section_id, unsigned int>*
+ get_section_order_map()
+ { return &this->section_order_map_; }
+
bool
is_section_ordering_specified()
{ return this->section_ordering_specified_; }
@@ -597,6 +603,18 @@ class Layout
size_t cie_length, const unsigned char* fde_data,
size_t fde_length);
+ // Scan a .debug_info or .debug_types section, and add summary
+ // information to the .gdb_index section.
+ template<int size, bool big_endian>
+ void
+ add_to_gdb_index(bool is_type_unit,
+ Sized_relobj<size, big_endian>* object,
+ const unsigned char* symbols,
+ off_t symbols_size,
+ unsigned int shndx,
+ unsigned int reloc_shndx,
+ unsigned int reloc_type);
+
// Handle a GNU stack note. This is called once per input object
// file. SEEN_GNU_STACK is true if the object file has a
// .note.GNU-stack section. GNU_STACK_FLAGS is the section flags
@@ -692,11 +710,11 @@ class Layout
{
// Debugging sections can only be recognized by name.
return (strncmp(name, ".debug", sizeof(".debug") - 1) == 0
- || strncmp(name, ".zdebug", sizeof(".zdebug") - 1) == 0
- || strncmp(name, ".gnu.linkonce.wi.",
- sizeof(".gnu.linkonce.wi.") - 1) == 0
- || strncmp(name, ".line", sizeof(".line") - 1) == 0
- || strncmp(name, ".stab", sizeof(".stab") - 1) == 0);
+ || strncmp(name, ".zdebug", sizeof(".zdebug") - 1) == 0
+ || strncmp(name, ".gnu.linkonce.wi.",
+ sizeof(".gnu.linkonce.wi.") - 1) == 0
+ || strncmp(name, ".line", sizeof(".line") - 1) == 0
+ || strncmp(name, ".stab", sizeof(".stab") - 1) == 0);
}
// Return true if RELOBJ is an input file whose base name matches
@@ -719,7 +737,7 @@ class Layout
// *KEPT_SECTION is set to the internal copy and the function return
// false.
bool
- find_or_add_kept_section(const std::string& name, Relobj* object,
+ find_or_add_kept_section(const std::string& name, Relobj* object,
unsigned int shndx, bool is_comdat,
bool is_group_name, Kept_section** kept_section);
@@ -886,7 +904,7 @@ class Layout
// Attach sections to segments.
void
- attach_sections_to_segments();
+ attach_sections_to_segments(const Target*);
// For relaxation clean up, we need to know output section data created
// from a linker script.
@@ -965,7 +983,7 @@ class Layout
// Find the first read-only PT_LOAD segment, creating one if
// necessary.
Output_segment*
- find_first_load_seg();
+ find_first_load_seg(const Target*);
// Count the local symbols in the regular symbol table and the dynamic
// symbol table, and build the respective string pools.
@@ -1062,7 +1080,7 @@ class Layout
// Attach a section to a segment.
void
- attach_section_to_segment(Output_section*);
+ attach_section_to_segment(const Target*, Output_section*);
// Get section order.
Output_section_order
@@ -1070,7 +1088,7 @@ class Layout
// Attach an allocated section to a segment.
void
- attach_allocated_section_to_segment(Output_section*);
+ attach_allocated_section_to_segment(const Target*, Output_section*);
// Make the .eh_frame section.
Output_section*
@@ -1117,7 +1135,7 @@ class Layout
bool
segment_precedes(const Output_segment* seg1, const Output_segment* seg2);
- // Use to save and restore segments during relaxation.
+ // Use to save and restore segments during relaxation.
typedef Unordered_map<const Output_segment*, const Output_segment*>
Segment_states;
@@ -1188,12 +1206,12 @@ class Layout
Relaxation_debug_check()
: section_infos_()
{ }
-
+
// Check that sections and special data are in reset states.
void
check_output_data_for_reset_values(const Layout::Section_list&,
const Layout::Data_list&);
-
+
// Record information of a section list.
void
read_sections(const Layout::Section_list&);
@@ -1201,7 +1219,7 @@ class Layout
// Verify a section list with recorded information.
void
verify_sections(const Layout::Section_list&);
-
+
private:
// Information we care about a section.
struct Section_info
@@ -1277,6 +1295,8 @@ class Layout
bool added_eh_frame_data_;
// The exception frame header output section if there is one.
Output_section* eh_frame_hdr_section_;
+ // The data for the .gdb_index section.
+ Gdb_index* gdb_index_data_;
// The space for the build ID checksum if there is one.
Output_section_data* build_id_note_;
// The output section containing dwarf abbreviations
@@ -1322,6 +1342,9 @@ class Layout
Segment_states* segment_states_;
// A relaxation debug checker. We only create one when in debugging mode.
Relaxation_debug_check* relaxation_debug_check_;
+ // Plugins specify section_ordering using this map. This is set in
+ // update_section_order in plugin.cc
+ std::map<Section_id, unsigned int> section_order_map_;
// Hash a pattern to its position in the section ordering file.
Unordered_map<std::string, unsigned int> input_section_position_;
// Vector of glob only patterns in the section_ordering file.
diff --git a/binutils-2.22/gold/main.cc b/binutils-2.22/gold/main.cc
index f6e7609..d329298 100644
--- a/binutils-2.22/gold/main.cc
+++ b/binutils-2.22/gold/main.cc
@@ -47,6 +47,7 @@
#include "gc.h"
#include "icf.h"
#include "incremental.h"
+#include "gdb-index.h"
#include "timer.h"
using namespace gold;
@@ -165,7 +166,10 @@ main(int argc, char** argv)
Timer timer;
if (command_line.options().stats())
- timer.start();
+ {
+ timer.start();
+ set_parameters_timer(&timer);
+ }
// Store some options in the globally accessible parameters.
set_parameters_options(&command_line.options());
@@ -252,7 +256,32 @@ main(int argc, char** argv)
if (command_line.options().stats())
{
- Timer::TimeStats elapsed = timer.get_elapsed_time();
+ timer.stamp(2);
+ Timer::TimeStats elapsed = timer.get_pass_time(0);
+ fprintf(stderr,
+ _("%s: initial tasks run time: " \
+ "(user: %ld.%06ld sys: %ld.%06ld wall: %ld.%06ld)\n"),
+ program_name,
+ elapsed.user / 1000, (elapsed.user % 1000) * 1000,
+ elapsed.sys / 1000, (elapsed.sys % 1000) * 1000,
+ elapsed.wall / 1000, (elapsed.wall % 1000) * 1000);
+ elapsed = timer.get_pass_time(1);
+ fprintf(stderr,
+ _("%s: middle tasks run time: " \
+ "(user: %ld.%06ld sys: %ld.%06ld wall: %ld.%06ld)\n"),
+ program_name,
+ elapsed.user / 1000, (elapsed.user % 1000) * 1000,
+ elapsed.sys / 1000, (elapsed.sys % 1000) * 1000,
+ elapsed.wall / 1000, (elapsed.wall % 1000) * 1000);
+ elapsed = timer.get_pass_time(2);
+ fprintf(stderr,
+ _("%s: final tasks run time: " \
+ "(user: %ld.%06ld sys: %ld.%06ld wall: %ld.%06ld)\n"),
+ program_name,
+ elapsed.user / 1000, (elapsed.user % 1000) * 1000,
+ elapsed.sys / 1000, (elapsed.sys % 1000) * 1000,
+ elapsed.wall / 1000, (elapsed.wall % 1000) * 1000);
+ elapsed = timer.get_elapsed_time();
fprintf(stderr,
_("%s: total run time: " \
"(user: %ld.%06ld sys: %ld.%06ld wall: %ld.%06ld)\n"),
@@ -273,6 +302,7 @@ main(int argc, char** argv)
program_name, static_cast<long long>(layout.output_file_size()));
symtab.print_stats();
layout.print_stats();
+ Gdb_index::print_stats();
Free_list::print_stats();
}
diff --git a/binutils-2.22/gold/merge.cc b/binutils-2.22/gold/merge.cc
index 093b6fc..dde43e9 100644
--- a/binutils-2.22/gold/merge.cc
+++ b/binutils-2.22/gold/merge.cc
@@ -406,27 +406,16 @@ bool
Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
{
section_size_type len;
- section_size_type uncompressed_size = 0;
- unsigned char* uncompressed_data = NULL;
- const unsigned char* p = object->section_contents(shndx, &len, false);
-
- if (object->section_is_compressed(shndx, &uncompressed_size))
- {
- uncompressed_data = new unsigned char[uncompressed_size];
- if (!decompress_input_section(p, len, uncompressed_data,
- uncompressed_size))
- object->error(_("could not decompress section %s"),
- object->section_name(shndx).c_str());
- p = uncompressed_data;
- len = uncompressed_size;
- }
+ bool is_new;
+ const unsigned char* p = object->decompressed_section_contents(shndx, &len,
+ &is_new);
section_size_type entsize = convert_to_section_size_type(this->entsize());
if (len % entsize != 0)
{
- if (uncompressed_data != NULL)
- delete[] uncompressed_data;
+ if (is_new)
+ delete[] p;
return false;
}
@@ -457,8 +446,8 @@ Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
if (this->keeps_input_sections())
record_input_section(object, shndx);
- if (uncompressed_data != NULL)
- delete[] uncompressed_data;
+ if (is_new)
+ delete[] p;
return true;
}
@@ -517,20 +506,10 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
unsigned int shndx)
{
section_size_type len;
- section_size_type uncompressed_size = 0;
- unsigned char* uncompressed_data = NULL;
- const unsigned char* pdata = object->section_contents(shndx, &len, false);
-
- if (object->section_is_compressed(shndx, &uncompressed_size))
- {
- uncompressed_data = new unsigned char[uncompressed_size];
- if (!decompress_input_section(pdata, len, uncompressed_data,
- uncompressed_size))
- object->error(_("could not decompress section %s"),
- object->section_name(shndx).c_str());
- pdata = uncompressed_data;
- len = uncompressed_size;
- }
+ bool is_new;
+ const unsigned char* pdata = object->decompressed_section_contents(shndx,
+ &len,
+ &is_new);
const Char_type* p = reinterpret_cast<const Char_type*>(pdata);
const Char_type* pend = p + len / sizeof(Char_type);
@@ -540,8 +519,8 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
{
object->error(_("mergeable string section length not multiple of "
"character size"));
- if (uncompressed_data != NULL)
- delete[] uncompressed_data;
+ if (is_new)
+ delete[] pdata;
return false;
}
@@ -606,8 +585,8 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
if (this->keeps_input_sections())
record_input_section(object, shndx);
- if (uncompressed_data != NULL)
- delete[] uncompressed_data;
+ if (is_new)
+ delete[] pdata;
return true;
}
diff --git a/binutils-2.22/gold/nacl.cc b/binutils-2.22/gold/nacl.cc
new file mode 100644
index 0000000..71be4e9
--- /dev/null
+++ b/binutils-2.22/gold/nacl.cc
@@ -0,0 +1,46 @@
+// nacl.cc -- Native Client support for gold
+
+// Copyright 2012 Free Software Foundation, Inc.
+
+// This file is part of gold.
+
+// 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.
+
+#include "gold.h"
+
+#include <cstdio>
+
+#include "nacl.h"
+#include "elfcpp.h"
+
+namespace gold
+{
+
+// Copied from object.cc:Object::error.
+void
+Sniff_file::error(const char* format, ...) const
+{
+ va_list args;
+ va_start(args, format);
+ char* buf = NULL;
+ if (vasprintf(&buf, format, args) < 0)
+ gold_nomem();
+ va_end(args);
+ gold_error(_("%s: %s"), this->file_.filename().c_str(), buf);
+ free(buf);
+}
+
+} // end namespace gold
diff --git a/binutils-2.22/gold/nacl.h b/binutils-2.22/gold/nacl.h
new file mode 100644
index 0000000..bf5853d
--- /dev/null
+++ b/binutils-2.22/gold/nacl.h
@@ -0,0 +1,243 @@
+// nacl.h -- Native Client support for gold -*- C++ -*-
+
+// Copyright 2012 Free Software Foundation, Inc.
+
+// This file is part of gold.
+
+// 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.
+
+#include "elfcpp_file.h"
+#include "fileread.h"
+#include "layout.h"
+#include "target-select.h"
+#include "target.h"
+
+#ifndef GOLD_NACL_H
+#define GOLD_NACL_H
+
+namespace gold
+{
+
+class Sniff_file
+{
+ public:
+ Sniff_file(Input_file* input_file, off_t offset)
+ : file_(input_file->file()), offset_(offset)
+ { }
+
+ class Location
+ {
+ public:
+ Location(off_t file_offset, off_t data_size)
+ : offset_(file_offset), size_(data_size)
+ { }
+
+ inline off_t offset() const
+ { return this->offset_; }
+
+ inline section_size_type size() const
+ { return this->size_; }
+
+ private:
+ off_t offset_;
+ section_size_type size_;
+ };
+
+ class View
+ {
+ public:
+ View(File_read& file, off_t file_offset, off_t data_size)
+ : data_(file.get_view(0, file_offset, data_size, false, false))
+ { }
+
+ const unsigned char* data()
+ { return this->data_; }
+
+ private:
+ const unsigned char* data_;
+ };
+
+ View view(off_t file_offset, off_t data_size)
+ {
+ return View(this->file_, this->offset_ + file_offset, data_size);
+ }
+
+ View view(Location loc)
+ {
+ return this->view(loc.offset(), loc.size());
+ }
+
+ // Report an error.
+ void
+ error(const char* format, ...) const ATTRIBUTE_PRINTF_2;
+
+ private:
+ File_read& file_;
+ off_t offset_;
+};
+
+
+template<class base_selector, class nacl_target>
+class Target_selector_nacl : public base_selector
+{
+ public:
+ Target_selector_nacl(const char* nacl_abi_name,
+ const char* bfd_name, const char* emulation)
+ : base_selector(), is_nacl_(false), nacl_abi_name_(nacl_abi_name),
+ bfd_name_(bfd_name), emulation_(emulation)
+ { }
+
+ protected:
+ virtual Target*
+ do_instantiate_target()
+ {
+ if (this->is_nacl_)
+ return new nacl_target();
+ return this->base_selector::do_instantiate_target();
+ }
+
+ virtual Target*
+ do_recognize(Input_file* file, off_t offset,
+ int machine, int osabi, int abiversion)
+ {
+ this->is_nacl_ = file != NULL && this->recognize_nacl_file(file, offset);
+ if (this->is_nacl_)
+ return this->instantiate_target();
+ return this->base_selector::do_recognize(file, offset,
+ machine, osabi, abiversion);
+ }
+
+ virtual Target*
+ do_recognize_by_bfd_name(const char* name)
+ {
+ gold_assert(this->bfd_name_ != NULL);
+ this->is_nacl_ = strcmp(name, this->bfd_name_) == 0;
+ if (this->is_nacl_)
+ return this->instantiate_target();
+ return this->base_selector::do_recognize_by_bfd_name(name);
+ }
+
+ virtual void
+ do_supported_bfd_names(std::vector<const char*>* names)
+ {
+ gold_assert(this->bfd_name_ != NULL);
+ this->base_selector::do_supported_bfd_names(names);
+ names->push_back(this->bfd_name_);
+ }
+
+ virtual void
+ do_supported_emulations(std::vector<const char*>* emulations)
+ {
+ gold_assert(this->emulation_ != NULL);
+ this->base_selector::do_supported_emulations(emulations);
+ emulations->push_back(this->emulation_);
+ }
+
+ virtual const char*
+ do_target_bfd_name(const Target* target)
+ {
+ return (!this->is_our_target(target)
+ ? NULL
+ : (this->is_nacl_
+ ? this->bfd_name_
+ : base_selector::do_target_bfd_name(target)));
+ }
+
+ private:
+ bool
+ recognize_nacl_file(Input_file* input_file, off_t offset)
+ {
+ if (this->is_big_endian())
+ {
+#if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG)
+# ifdef HAVE_TARGET_32_BIG
+ if (this->get_size() == 32)
+ return do_recognize_nacl_file<32, true>(input_file, offset);
+# endif
+# ifdef HAVE_TARGET_64_BIG
+ if (this->get_size() == 64)
+ return do_recognize_nacl_file<64, true>(input_file, offset);
+# endif
+#endif
+ gold_unreachable();
+ }
+ else
+ {
+#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE)
+# ifdef HAVE_TARGET_32_LITTLE
+ if (this->get_size() == 32)
+ return do_recognize_nacl_file<32, false>(input_file, offset);
+# endif
+# ifdef HAVE_TARGET_64_LITTLE
+ if (this->get_size() == 64)
+ return do_recognize_nacl_file<64, false>(input_file, offset);
+# endif
+#endif
+ gold_unreachable();
+ }
+ }
+
+ template<int size, bool big_endian>
+ bool
+ do_recognize_nacl_file(Input_file* input_file, off_t offset)
+ {
+ Sniff_file file(input_file, offset);
+ elfcpp::Elf_file<size, big_endian, Sniff_file> elf_file(&file);
+ const unsigned int shnum = elf_file.shnum();
+ for (unsigned int shndx = 1; shndx < shnum; ++shndx)
+ {
+ if (elf_file.section_type(shndx) == elfcpp::SHT_NOTE)
+ {
+ Sniff_file::Location loc = elf_file.section_contents(shndx);
+ if (loc.size() < (3 * 4
+ + align_address(sizeof "NaCl", 4)
+ + align_address(nacl_abi_name_.size() + 1, 4)))
+ continue;
+ Sniff_file::View view(file.view(loc));
+ const unsigned char* note_data = view.data();
+ if ((elfcpp::Swap<32, big_endian>::readval(note_data + 0)
+ == sizeof "NaCl")
+ && (elfcpp::Swap<32, big_endian>::readval(note_data + 4)
+ == nacl_abi_name_.size() + 1)
+ && (elfcpp::Swap<32, big_endian>::readval(note_data + 8)
+ == elfcpp::NT_VERSION))
+ {
+ const unsigned char* name = note_data + 12;
+ const unsigned char* desc = (name
+ + align_address(sizeof "NaCl", 4));
+ if (memcmp(name, "NaCl", sizeof "NaCl") == 0
+ && memcmp(desc, nacl_abi_name_.c_str(),
+ nacl_abi_name_.size() + 1) == 0)
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ // Whether we decided this was the NaCl target variant.
+ bool is_nacl_;
+ // The string found in the NaCl ABI note.
+ std::string nacl_abi_name_;
+ // BFD name of NaCl target, for compatibility.
+ const char* const bfd_name_;
+ // GNU linker emulation for this NaCl target, for compatibility.
+ const char* const emulation_;
+};
+
+} // end namespace gold
+
+#endif // !defined(GOLD_NACL_H)
diff --git a/binutils-2.22/gold/object.cc b/binutils-2.22/gold/object.cc
index 84a9646..e43ffdc 100644
--- a/binutils-2.22/gold/object.cc
+++ b/binutils-2.22/gold/object.cc
@@ -1,6 +1,7 @@
// object.cc -- support for an object file for linking in gold
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -178,16 +179,7 @@ Object::error(const char* format, ...) const
const unsigned char*
Object::section_contents(unsigned int shndx, section_size_type* plen,
bool cache)
-{
- Location loc(this->do_section_contents(shndx));
- *plen = convert_to_section_size_type(loc.data_size);
- if (*plen == 0)
- {
- static const unsigned char empty[1] = { '\0' };
- return empty;
- }
- return this->get_view(loc.file_offset, *plen, true, cache);
-}
+{ return this->do_section_contents(shndx, plen, cache); }
// Read the section data into SD. This is code common to Sized_relobj_file
// and Sized_dynobj, so we put it into Object.
@@ -277,28 +269,28 @@ Object::handle_split_stack_section(const char* name)
// Class Relobj
// To copy the symbols data read from the file to a local data structure.
-// This function is called from do_layout only while doing garbage
+// This function is called from do_layout only while doing garbage
// collection.
void
-Relobj::copy_symbols_data(Symbols_data* gc_sd, Read_symbols_data* sd,
- unsigned int section_header_size)
+Relobj::copy_symbols_data(Symbols_data* gc_sd, Read_symbols_data* sd,
+ unsigned int section_header_size)
{
- gc_sd->section_headers_data =
- new unsigned char[(section_header_size)];
+ gc_sd->section_headers_data =
+ new unsigned char[(section_header_size)];
memcpy(gc_sd->section_headers_data, sd->section_headers->data(),
- section_header_size);
- gc_sd->section_names_data =
- new unsigned char[sd->section_names_size];
+ section_header_size);
+ gc_sd->section_names_data =
+ new unsigned char[sd->section_names_size];
memcpy(gc_sd->section_names_data, sd->section_names->data(),
- sd->section_names_size);
+ sd->section_names_size);
gc_sd->section_names_size = sd->section_names_size;
if (sd->symbols != NULL)
{
- gc_sd->symbols_data =
- new unsigned char[sd->symbols_size];
+ gc_sd->symbols_data =
+ new unsigned char[sd->symbols_size];
memcpy(gc_sd->symbols_data, sd->symbols->data(),
- sd->symbols_size);
+ sd->symbols_size);
}
else
{
@@ -309,9 +301,9 @@ Relobj::copy_symbols_data(Symbols_data* gc_sd, Read_symbols_data* sd,
if (sd->symbol_names != NULL)
{
gc_sd->symbol_names_data =
- new unsigned char[sd->symbol_names_size];
+ new unsigned char[sd->symbol_names_size];
memcpy(gc_sd->symbol_names_data, sd->symbol_names->data(),
- sd->symbol_names_size);
+ sd->symbol_names_size);
}
else
{
@@ -327,22 +319,22 @@ Relobj::copy_symbols_data(Symbols_data* gc_sd, Read_symbols_data* sd,
bool
Relobj::is_section_name_included(const char* name)
{
- if (is_prefix_of(".ctors", name)
- || is_prefix_of(".dtors", name)
- || is_prefix_of(".note", name)
- || is_prefix_of(".init", name)
- || is_prefix_of(".fini", name)
- || is_prefix_of(".gcc_except_table", name)
- || is_prefix_of(".jcr", name)
- || is_prefix_of(".preinit_array", name)
- || (is_prefix_of(".text", name)
- && strstr(name, "personality"))
- || (is_prefix_of(".data", name)
- && strstr(name, "personality"))
+ if (is_prefix_of(".ctors", name)
+ || is_prefix_of(".dtors", name)
+ || is_prefix_of(".note", name)
+ || is_prefix_of(".init", name)
+ || is_prefix_of(".fini", name)
+ || is_prefix_of(".gcc_except_table", name)
+ || is_prefix_of(".jcr", name)
+ || is_prefix_of(".preinit_array", name)
+ || (is_prefix_of(".text", name)
+ && strstr(name, "personality"))
+ || (is_prefix_of(".data", name)
+ && strstr(name, "personality"))
|| (is_prefix_of(".gnu.linkonce.d", name)
&& strstr(name, "personality")))
{
- return true;
+ return true;
}
return false;
}
@@ -550,8 +542,57 @@ Sized_relobj_file<size, big_endian>::find_eh_frame(
return false;
}
+// Return TRUE if this is a section whose contents will be needed in the
+// Add_symbols task. This function is only called for sections that have
+// already passed the test in is_compressed_debug_section(), so we know
+// that the section name begins with ".zdebug".
+
+static bool
+need_decompressed_section(const char* name)
+{
+ // Skip over the ".zdebug" and a quick check for the "_".
+ name += 7;
+ if (*name++ != '_')
+ return false;
+
+#ifdef ENABLE_THREADS
+ // Decompressing these sections now will help only if we're
+ // multithreaded.
+ if (parameters->options().threads())
+ {
+ // We will need .zdebug_str if this is not an incremental link
+ // (i.e., we are processing string merge sections) or if we need
+ // to build a gdb index.
+ if ((!parameters->incremental() || parameters->options().gdb_index())
+ && strcmp(name, "str") == 0)
+ return true;
+
+ // We will need these other sections when building a gdb index.
+ if (parameters->options().gdb_index()
+ && (strcmp(name, "info") == 0
+ || strcmp(name, "types") == 0
+ || strcmp(name, "pubnames") == 0
+ || strcmp(name, "pubtypes") == 0
+ || strcmp(name, "ranges") == 0
+ || strcmp(name, "abbrev") == 0))
+ return true;
+ }
+#endif
+
+ // Even when single-threaded, we will need .zdebug_str if this is
+ // not an incremental link and we are building a gdb index.
+ // Otherwise, we would decompress the section twice: once for
+ // string merge processing, and once for building the gdb index.
+ if (!parameters->incremental()
+ && parameters->options().gdb_index()
+ && strcmp(name, "str") == 0)
+ return true;
+
+ return false;
+}
+
// Build a table for any compressed debug sections, mapping each section index
-// to the uncompressed size.
+// to the uncompressed size and (if needed) the decompressed contents.
template<int size, bool big_endian>
Compressed_section_map*
@@ -562,9 +603,10 @@ build_compressed_section_map(
section_size_type names_size,
Sized_relobj_file<size, big_endian>* obj)
{
- Compressed_section_map* uncompressed_sizes = new Compressed_section_map();
+ Compressed_section_map* uncompressed_map = new Compressed_section_map();
const unsigned int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
const unsigned char* p = pshdrs + shdr_size;
+
for (unsigned int i = 1; i < shnum; ++i, p += shdr_size)
{
typename elfcpp::Shdr<size, big_endian> shdr(p);
@@ -585,13 +627,28 @@ build_compressed_section_map(
const unsigned char* contents =
obj->section_contents(i, &len, false);
uint64_t uncompressed_size = get_uncompressed_size(contents, len);
+ Compressed_section_info info;
+ info.size = convert_to_section_size_type(uncompressed_size);
+ info.contents = NULL;
if (uncompressed_size != -1ULL)
- (*uncompressed_sizes)[i] =
- convert_to_section_size_type(uncompressed_size);
+ {
+ unsigned char* uncompressed_data = NULL;
+ if (need_decompressed_section(name))
+ {
+ uncompressed_data = new unsigned char[uncompressed_size];
+ if (decompress_input_section(contents, len,
+ uncompressed_data,
+ uncompressed_size))
+ info.contents = uncompressed_data;
+ else
+ delete[] uncompressed_data;
+ }
+ (*uncompressed_map)[i] = info;
+ }
}
}
}
- return uncompressed_sizes;
+ return uncompressed_map;
}
// Read the sections and symbols from an object file.
@@ -600,6 +657,8 @@ template<int size, bool big_endian>
void
Sized_relobj_file<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
{
+ bool need_local_symbols = false;
+
this->read_section_data(&this->elf_file_, sd);
const unsigned char* const pshdrs = sd->section_headers->data();
@@ -611,13 +670,21 @@ Sized_relobj_file<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
if (memmem(names, sd->section_names_size, ".eh_frame", 10) != NULL)
{
if (this->find_eh_frame(pshdrs, names, sd->section_names_size))
- this->has_eh_frame_ = true;
+ this->has_eh_frame_ = true;
}
if (memmem(names, sd->section_names_size, ".zdebug_", 8) != NULL)
this->compressed_sections_ =
- build_compressed_section_map(pshdrs, this->shnum(), names,
+ build_compressed_section_map(pshdrs, this->shnum(), names,
sd->section_names_size, this);
+ if (this->has_eh_frame_
+ || (!parameters->options().relocatable()
+ && parameters->options().gdb_index()
+ && (memmem(names, sd->section_names_size, "debug_info", 12) == 0
+ || memmem(names, sd->section_names_size, "debug_types",
+ 13) == 0)))
+ need_local_symbols = true;
+
sd->symbols = NULL;
sd->symbols_size = 0;
sd->external_symbols_offset = 0;
@@ -635,7 +702,8 @@ Sized_relobj_file<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
+ this->symtab_shndx_ * This::shdr_size);
gold_assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB);
- // If this object has a .eh_frame section, we need all the symbols.
+ // If this object has a .eh_frame section, or if building a .gdb_index
+ // section and there is debug info, we need all the symbols.
// Otherwise we only need the external symbols. While it would be
// simpler to just always read all the symbols, I've seen object
// files with well over 2000 local symbols, which for a 64-bit
@@ -653,8 +721,8 @@ Sized_relobj_file<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
off_t extoff = dataoff + locsize;
section_size_type extsize = datasize - locsize;
- off_t readoff = this->has_eh_frame_ ? dataoff : extoff;
- section_size_type readsize = this->has_eh_frame_ ? datasize : extsize;
+ off_t readoff = need_local_symbols ? dataoff : extoff;
+ section_size_type readsize = need_local_symbols ? datasize : extsize;
if (readsize == 0)
{
@@ -686,7 +754,7 @@ Sized_relobj_file<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
sd->symbols = fvsymtab;
sd->symbols_size = readsize;
- sd->external_symbols_offset = this->has_eh_frame_ ? locsize : 0;
+ sd->external_symbols_offset = need_local_symbols ? locsize : 0;
sd->symbol_names = fvstrtab;
sd->symbol_names_size =
convert_to_section_size_type(strtabshdr.get_sh_size());
@@ -807,7 +875,7 @@ Sized_relobj_file<size, big_endian>::include_section_group(
}
typename This::Shdr member_shdr(shdrs + sym_shndx * This::shdr_size);
if (member_shdr.get_sh_name() < section_names_size)
- signature = section_names + member_shdr.get_sh_name();
+ signature = section_names + member_shdr.get_sh_name();
}
// Record this section group in the layout, and see whether we've already
@@ -861,18 +929,18 @@ Sized_relobj_file<size, big_endian>::include_section_group(
// Check for an earlier section number, since we're going to get
// it wrong--we may have already decided to include the section.
if (shndx < index)
- this->error(_("invalid section group %u refers to earlier section %u"),
- index, shndx);
+ this->error(_("invalid section group %u refers to earlier section %u"),
+ index, shndx);
// Get the name of the member section.
typename This::Shdr member_shdr(shdrs + shndx * This::shdr_size);
if (member_shdr.get_sh_name() >= section_names_size)
- {
- // This is an error, but it will be diagnosed eventually
- // in do_layout, so we don't need to do anything here but
- // ignore it.
- continue;
- }
+ {
+ // This is an error, but it will be diagnosed eventually
+ // in do_layout, so we don't need to do anything here but
+ // ignore it.
+ continue;
+ }
std::string mname(section_names + member_shdr.get_sh_name());
if (include_group)
@@ -882,11 +950,11 @@ Sized_relobj_file<size, big_endian>::include_section_group(
member_shdr.get_sh_size());
}
else
- {
- (*omit)[shndx] = true;
+ {
+ (*omit)[shndx] = true;
if (is_comdat)
- {
+ {
Relobj* kept_object = kept_section->object();
if (kept_section->is_comdat())
{
@@ -920,8 +988,8 @@ Sized_relobj_file<size, big_endian>::include_section_group(
this->set_kept_comdat_section(shndx, kept_object,
kept_section->shndx());
}
- }
- }
+ }
+ }
}
if (relocate_group)
@@ -1095,15 +1163,15 @@ Sized_relobj_file<size, big_endian>::layout_eh_frame_section(
// Lay out the input sections. We walk through the sections and check
// whether they should be included in the link. If they should, we
// pass them to the Layout object, which will return an output section
-// and an offset.
-// During garbage collection (--gc-sections) and identical code folding
-// (--icf), this function is called twice. When it is called the first
+// and an offset.
+// During garbage collection (--gc-sections) and identical code folding
+// (--icf), this function is called twice. When it is called the first
// time, it is for setting up some sections as roots to a work-list for
-// --gc-sections and to do comdat processing. Actual layout happens the
-// second time around after all the relevant sections have been determined.
-// The first time, is_worklist_ready or is_icf_ready is false. It is then
-// set to true after the garbage collection worklist or identical code
-// folding is processed and the relevant sections to be kept are
+// --gc-sections and to do comdat processing. Actual layout happens the
+// second time around after all the relevant sections have been determined.
+// The first time, is_worklist_ready or is_icf_ready is false. It is then
+// set to true after the garbage collection worklist or identical code
+// folding is processed and the relevant sections to be kept are
// determined. Then, this function is called again to layout the sections.
template<int size, bool big_endian>
@@ -1113,18 +1181,18 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
Read_symbols_data* sd)
{
const unsigned int shnum = this->shnum();
- bool is_gc_pass_one = ((parameters->options().gc_sections()
- && !symtab->gc()->is_worklist_ready())
- || (parameters->options().icf_enabled()
- && !symtab->icf()->is_icf_ready()));
-
- bool is_gc_pass_two = ((parameters->options().gc_sections()
- && symtab->gc()->is_worklist_ready())
- || (parameters->options().icf_enabled()
- && symtab->icf()->is_icf_ready()));
+ bool is_gc_pass_one = ((parameters->options().gc_sections()
+ && !symtab->gc()->is_worklist_ready())
+ || (parameters->options().icf_enabled()
+ && !symtab->icf()->is_icf_ready()));
+
+ bool is_gc_pass_two = ((parameters->options().gc_sections()
+ && symtab->gc()->is_worklist_ready())
+ || (parameters->options().icf_enabled()
+ && symtab->icf()->is_icf_ready()));
bool is_gc_or_icf = (parameters->options().gc_sections()
- || parameters->options().icf_enabled());
+ || parameters->options().icf_enabled());
// Both is_gc_pass_one and is_gc_pass_two should not be true.
gold_assert(!(is_gc_pass_one && is_gc_pass_two));
@@ -1134,8 +1202,8 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
Symbols_data* gc_sd = NULL;
if (is_gc_pass_one)
{
- // During garbage collection save the symbols data to use it when
- // re-entering this function.
+ // During garbage collection save the symbols data to use it when
+ // re-entering this function.
gc_sd = new Symbols_data;
this->copy_symbols_data(gc_sd, sd, This::shdr_size * shnum);
this->set_symbols_data(gc_sd);
@@ -1151,7 +1219,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
section_size_type symbols_size;
const unsigned char* symbol_names_data = NULL;
section_size_type symbol_names_size;
-
+
if (is_gc_or_icf)
{
section_headers_data = gc_sd->section_headers_data;
@@ -1166,10 +1234,10 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
section_headers_data = sd->section_headers->data();
section_names_size = sd->section_names_size;
if (sd->symbols != NULL)
- symbols_data = sd->symbols->data();
+ symbols_data = sd->symbols->data();
symbols_size = sd->symbols_size;
if (sd->symbol_names != NULL)
- symbol_names_data = sd->symbol_names->data();
+ symbol_names_data = sd->symbol_names->data();
symbol_names_size = sd->symbol_names_size;
}
@@ -1178,9 +1246,9 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
const unsigned char* pshdrs;
// Get the section names.
- const unsigned char* pnamesu = (is_gc_or_icf)
- ? gc_sd->section_names_data
- : sd->section_names->data();
+ const unsigned char* pnamesu = (is_gc_or_icf)
+ ? gc_sd->section_names_data
+ : sd->section_names->data();
const char* pnames = reinterpret_cast<const char*>(pnamesu);
@@ -1204,7 +1272,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
// Count the number of sections whose layout will be deferred.
if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
- ++num_sections_to_defer;
+ ++num_sections_to_defer;
unsigned int sh_type = shdr.get_sh_type();
if (sh_type == elfcpp::SHT_REL || sh_type == elfcpp::SHT_RELA)
@@ -1241,12 +1309,12 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
if (this->input_file()->just_symbols())
{
if (!is_gc_pass_two)
- {
- delete sd->section_headers;
- sd->section_headers = NULL;
- delete sd->section_names;
- sd->section_names = NULL;
- }
+ {
+ delete sd->section_headers;
+ sd->section_headers = NULL;
+ delete sd->section_names;
+ sd->section_names = NULL;
+ }
return;
}
@@ -1273,6 +1341,10 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
// Keep track of .eh_frame sections.
std::vector<unsigned int> eh_frame_sections;
+ // Keep track of .debug_info and .debug_types sections.
+ std::vector<unsigned int> debug_info_sections;
+ std::vector<unsigned int> debug_types_sections;
+
// Skip the first, dummy, section.
pshdrs = shdrs + This::shdr_size;
for (unsigned int i = 1; i < shnum; ++i, pshdrs += This::shdr_size)
@@ -1289,22 +1361,22 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
const char* name = pnames + shdr.get_sh_name();
if (!is_gc_pass_two)
- {
- if (this->handle_gnu_warning_section(name, i, symtab))
- {
- if (!relocatable && !parameters->options().shared())
- omit[i] = true;
+ {
+ if (this->handle_gnu_warning_section(name, i, symtab))
+ {
+ if (!relocatable && !parameters->options().shared())
+ omit[i] = true;
}
- // The .note.GNU-stack section is special. It gives the
- // protection flags that this object file requires for the stack
- // in memory.
- if (strcmp(name, ".note.GNU-stack") == 0)
- {
+ // The .note.GNU-stack section is special. It gives the
+ // protection flags that this object file requires for the stack
+ // in memory.
+ if (strcmp(name, ".note.GNU-stack") == 0)
+ {
seen_gnu_stack = true;
gnu_stack_flags |= shdr.get_sh_flags();
omit[i] = true;
- }
+ }
// The .note.GNU-split-stack section is also special. It
// indicates that the object was compiled with
@@ -1321,23 +1393,23 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
omit[i] = true;
}
- bool discard = omit[i];
- if (!discard)
- {
+ bool discard = omit[i];
+ if (!discard)
+ {
if (shdr.get_sh_type() == elfcpp::SHT_GROUP)
- {
- if (!this->include_section_group(symtab, layout, i, name,
- shdrs, pnames,
- section_names_size,
- &omit))
+ {
+ if (!this->include_section_group(symtab, layout, i, name,
+ shdrs, pnames,
+ section_names_size,
+ &omit))
+ discard = true;
+ }
+ else if ((shdr.get_sh_flags() & elfcpp::SHF_GROUP) == 0
+ && Layout::is_linkonce(name))
+ {
+ if (!this->include_linkonce_section(layout, i, name, shdr))
discard = true;
- }
- else if ((shdr.get_sh_flags() & elfcpp::SHF_GROUP) == 0
- && Layout::is_linkonce(name))
- {
- if (!this->include_linkonce_section(layout, i, name, shdr))
- discard = true;
- }
+ }
}
// Add the section to the incremental inputs layout.
@@ -1353,32 +1425,32 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
incremental_inputs->report_input_section(this, i, name, sh_size);
}
- if (discard)
- {
+ if (discard)
+ {
// Do not include this section in the link.
out_sections[i] = NULL;
- out_section_offsets[i] = invalid_address;
+ out_section_offsets[i] = invalid_address;
continue;
- }
- }
-
+ }
+ }
+
if (is_gc_pass_one && parameters->options().gc_sections())
- {
- if (this->is_section_name_included(name)
- || shdr.get_sh_type() == elfcpp::SHT_INIT_ARRAY
- || shdr.get_sh_type() == elfcpp::SHT_FINI_ARRAY)
- {
- symtab->gc()->worklist().push(Section_id(this, i));
- }
- // If the section name XXX can be represented as a C identifier
- // it cannot be discarded if there are references to
- // __start_XXX and __stop_XXX symbols. These need to be
- // specially handled.
- if (is_cident(name))
- {
- symtab->gc()->add_cident_section(name, Section_id(this, i));
- }
- }
+ {
+ if (this->is_section_name_included(name)
+ || shdr.get_sh_type() == elfcpp::SHT_INIT_ARRAY
+ || shdr.get_sh_type() == elfcpp::SHT_FINI_ARRAY)
+ {
+ symtab->gc()->worklist().push(Section_id(this, i));
+ }
+ // If the section name XXX can be represented as a C identifier
+ // it cannot be discarded if there are references to
+ // __start_XXX and __stop_XXX symbols. These need to be
+ // specially handled.
+ if (is_cident(name))
+ {
+ symtab->gc()->add_cident_section(name, Section_id(this, i));
+ }
+ }
// When doing a relocatable link we are going to copy input
// reloc sections into the output. We only want to copy the
@@ -1404,124 +1476,139 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
// determine which sections are being discarded, and discard the
// corresponding information.
if (!relocatable
- && strcmp(name, ".eh_frame") == 0
- && this->check_eh_frame_flags(&shdr))
- {
- if (is_gc_pass_one)
- {
- out_sections[i] = reinterpret_cast<Output_section*>(1);
- out_section_offsets[i] = invalid_address;
- }
- else if (should_defer_layout)
+ && strcmp(name, ".eh_frame") == 0
+ && this->check_eh_frame_flags(&shdr))
+ {
+ if (is_gc_pass_one)
+ {
+ out_sections[i] = reinterpret_cast<Output_section*>(1);
+ out_section_offsets[i] = invalid_address;
+ }
+ else if (should_defer_layout)
this->deferred_layout_.push_back(Deferred_layout(i, name,
pshdrs,
reloc_shndx[i],
reloc_type[i]));
else
- eh_frame_sections.push_back(i);
- continue;
- }
+ eh_frame_sections.push_back(i);
+ continue;
+ }
if (is_gc_pass_two && parameters->options().gc_sections())
- {
- // This is executed during the second pass of garbage
- // collection. do_layout has been called before and some
- // sections have been already discarded. Simply ignore
- // such sections this time around.
- if (out_sections[i] == NULL)
- {
- gold_assert(out_section_offsets[i] == invalid_address);
- continue;
- }
- if (((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0)
- && symtab->gc()->is_section_garbage(this, i))
- {
- if (parameters->options().print_gc_sections())
- gold_info(_("%s: removing unused section from '%s'"
- " in file '%s'"),
- program_name, this->section_name(i).c_str(),
- this->name().c_str());
- out_sections[i] = NULL;
- out_section_offsets[i] = invalid_address;
- continue;
- }
- }
+ {
+ // This is executed during the second pass of garbage
+ // collection. do_layout has been called before and some
+ // sections have been already discarded. Simply ignore
+ // such sections this time around.
+ if (out_sections[i] == NULL)
+ {
+ gold_assert(out_section_offsets[i] == invalid_address);
+ continue;
+ }
+ if (((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0)
+ && symtab->gc()->is_section_garbage(this, i))
+ {
+ if (parameters->options().print_gc_sections())
+ gold_info(_("%s: removing unused section from '%s'"
+ " in file '%s'"),
+ program_name, this->section_name(i).c_str(),
+ this->name().c_str());
+ out_sections[i] = NULL;
+ out_section_offsets[i] = invalid_address;
+ continue;
+ }
+ }
if (is_gc_pass_two && parameters->options().icf_enabled())
- {
- if (out_sections[i] == NULL)
- {
- gold_assert(out_section_offsets[i] == invalid_address);
- continue;
- }
- if (((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0)
- && symtab->icf()->is_section_folded(this, i))
- {
- if (parameters->options().print_icf_sections())
- {
- Section_id folded =
- symtab->icf()->get_folded_section(this, i);
- Relobj* folded_obj =
- reinterpret_cast<Relobj*>(folded.first);
- gold_info(_("%s: ICF folding section '%s' in file '%s'"
- "into '%s' in file '%s'"),
- program_name, this->section_name(i).c_str(),
- this->name().c_str(),
- folded_obj->section_name(folded.second).c_str(),
- folded_obj->name().c_str());
- }
- out_sections[i] = NULL;
- out_section_offsets[i] = invalid_address;
- continue;
- }
- }
+ {
+ if (out_sections[i] == NULL)
+ {
+ gold_assert(out_section_offsets[i] == invalid_address);
+ continue;
+ }
+ if (((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0)
+ && symtab->icf()->is_section_folded(this, i))
+ {
+ if (parameters->options().print_icf_sections())
+ {
+ Section_id folded =
+ symtab->icf()->get_folded_section(this, i);
+ Relobj* folded_obj =
+ reinterpret_cast<Relobj*>(folded.first);
+ gold_info(_("%s: ICF folding section '%s' in file '%s'"
+ "into '%s' in file '%s'"),
+ program_name, this->section_name(i).c_str(),
+ this->name().c_str(),
+ folded_obj->section_name(folded.second).c_str(),
+ folded_obj->name().c_str());
+ }
+ out_sections[i] = NULL;
+ out_section_offsets[i] = invalid_address;
+ continue;
+ }
+ }
// Defer layout here if input files are claimed by plugins. When gc
// is turned on this function is called twice. For the second call
// should_defer_layout should be false.
if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
- {
- gold_assert(!is_gc_pass_two);
- this->deferred_layout_.push_back(Deferred_layout(i, name,
- pshdrs,
- reloc_shndx[i],
- reloc_type[i]));
- // Put dummy values here; real values will be supplied by
- // do_layout_deferred_sections.
- out_sections[i] = reinterpret_cast<Output_section*>(2);
- out_section_offsets[i] = invalid_address;
- continue;
- }
+ {
+ gold_assert(!is_gc_pass_two);
+ this->deferred_layout_.push_back(Deferred_layout(i, name,
+ pshdrs,
+ reloc_shndx[i],
+ reloc_type[i]));
+ // Put dummy values here; real values will be supplied by
+ // do_layout_deferred_sections.
+ out_sections[i] = reinterpret_cast<Output_section*>(2);
+ out_section_offsets[i] = invalid_address;
+ continue;
+ }
// During gc_pass_two if a section that was previously deferred is
// found, do not layout the section as layout_deferred_sections will
// do it later from gold.cc.
- if (is_gc_pass_two
- && (out_sections[i] == reinterpret_cast<Output_section*>(2)))
- continue;
+ if (is_gc_pass_two
+ && (out_sections[i] == reinterpret_cast<Output_section*>(2)))
+ continue;
if (is_gc_pass_one)
- {
- // This is during garbage collection. The out_sections are
- // assigned in the second call to this function.
- out_sections[i] = reinterpret_cast<Output_section*>(1);
- out_section_offsets[i] = invalid_address;
- }
+ {
+ // This is during garbage collection. The out_sections are
+ // assigned in the second call to this function.
+ out_sections[i] = reinterpret_cast<Output_section*>(1);
+ out_section_offsets[i] = invalid_address;
+ }
else
- {
- // When garbage collection is switched on the actual layout
- // only happens in the second call.
- this->layout_section(layout, i, name, shdr, reloc_shndx[i],
- reloc_type[i]);
- }
+ {
+ // When garbage collection is switched on the actual layout
+ // only happens in the second call.
+ this->layout_section(layout, i, name, shdr, reloc_shndx[i],
+ reloc_type[i]);
+
+ // When generating a .gdb_index section, we do additional
+ // processing of .debug_info and .debug_types sections after all
+ // the other sections for the same reason as above.
+ if (!relocatable
+ && parameters->options().gdb_index()
+ && !(shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
+ {
+ if (strcmp(name, ".debug_info") == 0
+ || strcmp(name, ".zdebug_info") == 0)
+ debug_info_sections.push_back(i);
+ else if (strcmp(name, ".debug_types") == 0
+ || strcmp(name, ".zdebug_types") == 0)
+ debug_types_sections.push_back(i);
+ }
+ }
}
if (!is_gc_pass_two)
layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags, this);
// When doing a relocatable link handle the reloc sections at the
- // end. Garbage collection and Identical Code Folding is not
- // turned on for relocatable code.
+ // end. Garbage collection and Identical Code Folding is not
+ // turned on for relocatable code.
if (emit_relocs)
this->size_relocatable_relocs();
@@ -1545,20 +1632,20 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
Output_section* data_section = out_sections[data_shndx];
if (data_section == reinterpret_cast<Output_section*>(2))
- {
- // The layout for the data section was deferred, so we need
- // to defer the relocation section, too.
+ {
+ // The layout for the data section was deferred, so we need
+ // to defer the relocation section, too.
const char* name = pnames + shdr.get_sh_name();
- this->deferred_layout_relocs_.push_back(
- Deferred_layout(i, name, pshdr, 0, elfcpp::SHT_NULL));
+ this->deferred_layout_relocs_.push_back(
+ Deferred_layout(i, name, pshdr, 0, elfcpp::SHT_NULL));
out_sections[i] = reinterpret_cast<Output_section*>(2);
- out_section_offsets[i] = invalid_address;
- continue;
- }
+ out_section_offsets[i] = invalid_address;
+ continue;
+ }
if (data_section == NULL)
{
out_sections[i] = NULL;
- out_section_offsets[i] = invalid_address;
+ out_section_offsets[i] = invalid_address;
continue;
}
@@ -1593,6 +1680,29 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
reloc_type[i]);
}
+ // When building a .gdb_index section, scan the .debug_info and
+ // .debug_types sections.
+ gold_assert(!is_gc_pass_one
+ || (debug_info_sections.empty() && debug_types_sections.empty()));
+ for (std::vector<unsigned int>::const_iterator p
+ = debug_info_sections.begin();
+ p != debug_info_sections.end();
+ ++p)
+ {
+ unsigned int i = *p;
+ layout->add_to_gdb_index(false, this, symbols_data, symbols_size,
+ i, reloc_shndx[i], reloc_type[i]);
+ }
+ for (std::vector<unsigned int>::const_iterator p
+ = debug_types_sections.begin();
+ p != debug_types_sections.end();
+ ++p)
+ {
+ unsigned int i = *p;
+ layout->add_to_gdb_index(true, this, symbols_data, symbols_size,
+ i, reloc_shndx[i], reloc_type[i]);
+ }
+
if (is_gc_pass_two)
{
delete[] gc_sd->section_headers_data;
@@ -1627,7 +1737,7 @@ Sized_relobj_file<size, big_endian>::do_layout_deferred_sections(Layout* layout)
// If the section is not included, it is because the garbage collector
// decided it is not needed. Avoid reverting that decision.
if (!this->is_section_included(deferred->shndx_))
- continue;
+ continue;
if (parameters->options().relocatable()
|| deferred->name_ != ".eh_frame"
@@ -1671,7 +1781,7 @@ Sized_relobj_file<size, big_endian>::do_layout_deferred_sections(Layout* layout)
if (data_section == NULL)
{
out_sections[shndx] = NULL;
- out_section_offsets[shndx] = invalid_address;
+ out_section_offsets[shndx] = invalid_address;
continue;
}
@@ -1746,7 +1856,7 @@ Sized_relobj_file<size, big_endian>::do_should_include_member(
sd->symbols->data() + sd->external_symbols_offset;
const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
size_t symcount = ((sd->symbols_size - sd->external_symbols_offset)
- / sym_size);
+ / sym_size);
const unsigned char* p = syms;
@@ -1792,7 +1902,7 @@ Sized_relobj_file<size, big_endian>::do_for_all_global_symbols(
sd->symbols->data() + sd->external_symbols_offset;
const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
size_t symcount = ((sd->symbols_size - sd->external_symbols_offset)
- / sym_size);
+ / sym_size);
const unsigned char* p = syms;
for (size_t i = 0; i < symcount; ++i, p += sym_size)
@@ -1819,7 +1929,8 @@ Sized_relobj_file<size, big_endian>::local_has_plt_offset(
template<int size, bool big_endian>
unsigned int
-Sized_relobj_file<size, big_endian>::local_plt_offset(unsigned int symndx) const
+Sized_relobj_file<size, big_endian>::do_local_plt_offset(
+ unsigned int symndx) const
{
typename Local_plt_offsets::const_iterator p =
this->local_plt_offsets_.find(symndx);
@@ -1916,16 +2027,16 @@ Sized_relobj_file<size, big_endian>::do_count_local_symbols(Stringpool* pool,
if ((shndx < shnum && out_sections[shndx] == NULL)
|| shndx == this->discarded_eh_frame_shndx_)
- {
+ {
lv.set_no_output_symtab_entry();
- gold_assert(!lv.needs_output_dynsym_entry());
- continue;
- }
+ gold_assert(!lv.needs_output_dynsym_entry());
+ continue;
+ }
if (sym.get_st_type() == elfcpp::STT_SECTION)
{
lv.set_no_output_symtab_entry();
- gold_assert(!lv.needs_output_dynsym_entry());
+ gold_assert(!lv.needs_output_dynsym_entry());
continue;
}
@@ -1942,10 +2053,10 @@ Sized_relobj_file<size, big_endian>::do_count_local_symbols(Stringpool* pool,
// If needed, add the symbol to the dynamic symbol table string pool.
if (lv.needs_output_dynsym_entry())
- {
- dynpool->add(name, true, NULL);
- ++dyncount;
- }
+ {
+ dynpool->add(name, true, NULL);
+ ++dyncount;
+ }
if (strip_all
|| (discard_all && lv.may_be_discarded_from_output_symtab()))
@@ -1979,10 +2090,10 @@ Sized_relobj_file<size, big_endian>::do_count_local_symbols(Stringpool* pool,
// Discard the local symbol if -retain_symbols_file is specified
// and the local symbol is not in that file.
if (!parameters->options().should_retain_symbol(name))
- {
- lv.set_no_output_symtab_entry();
- continue;
- }
+ {
+ lv.set_no_output_symtab_entry();
+ continue;
+ }
// Add the symbol to the symbol table string pool.
pool->add(name, true, NULL);
@@ -2012,9 +2123,9 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
bool is_ordinary;
unsigned int shndx = lv_in->input_shndx(&is_ordinary);
-
+
// Set the output symbol value.
-
+
if (!is_ordinary)
{
if (shndx == elfcpp::SHN_ABS || Symbol::is_common_shndx(shndx))
@@ -2036,7 +2147,7 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
lv_out->set_output_value(0);
return This::CFLV_ERROR;
}
-
+
Output_section* os = out_sections[shndx];
Address secoffset = out_offsets[shndx];
if (symtab->is_section_folded(this, shndx))
@@ -2051,7 +2162,7 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
os = folded_obj->output_section(folded.second);
gold_assert(os != NULL);
secoffset = folded_obj->get_output_section_offset(folded.second);
-
+
// This could be a relaxed input section.
if (secoffset == invalid_address)
{
@@ -2061,7 +2172,7 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
secoffset = relaxed_section->address() - os->address();
}
}
-
+
if (os == NULL)
{
// This local symbol belongs to a section we are discarding.
@@ -2073,7 +2184,7 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
else if (secoffset == invalid_address)
{
uint64_t start;
-
+
// This is a SHF_MERGE section or one which otherwise
// requires special handling.
if (shndx == this->discarded_eh_frame_shndx_)
@@ -2226,10 +2337,10 @@ Sized_relobj_file<size, big_endian>::do_set_local_dynsym_indexes(
{
Symbol_value<size>& lv(this->local_values_[i]);
if (lv.needs_output_dynsym_entry())
- {
- lv.set_output_dynsym_index(index);
- ++index;
- }
+ {
+ lv.set_output_dynsym_index(index);
+ ++index;
+ }
}
return index;
}
@@ -2258,12 +2369,12 @@ Sized_relobj_file<size, big_endian>::do_section_flags(unsigned int shndx)
if (sd != NULL)
{
const unsigned char* pshdrs = sd->section_headers_data
- + This::shdr_size * shndx;
+ + This::shdr_size * shndx;
typename This::Shdr shdr(pshdrs);
- return shdr.get_sh_flags();
+ return shdr.get_sh_flags();
}
// If sd is NULL, read the section header from the file.
- return this->elf_file_.section_flags(shndx);
+ return this->elf_file_.section_flags(shndx);
}
// Get the section's ent size from Symbols_data. Called by get_section_contents
@@ -2277,9 +2388,9 @@ Sized_relobj_file<size, big_endian>::do_section_entsize(unsigned int shndx)
gold_assert(sd != NULL);
const unsigned char* pshdrs = sd->section_headers_data
- + This::shdr_size * shndx;
+ + This::shdr_size * shndx;
typename This::Shdr shdr(pshdrs);
- return shdr.get_sh_entsize();
+ return shdr.get_sh_entsize();
}
// Write out the local symbols.
@@ -2344,7 +2455,7 @@ Sized_relobj_file<size, big_endian>::write_local_symbols(
unsigned char* dyn_oview = NULL;
if (dyn_output_size > 0)
dyn_oview = of->get_output_view(this->local_dynsym_offset_,
- dyn_output_size);
+ dyn_output_size);
const Output_sections out_sections(this->output_sections());
@@ -2380,38 +2491,38 @@ Sized_relobj_file<size, big_endian>::write_local_symbols(
// Write the symbol to the output symbol table.
if (lv.has_output_symtab_entry())
- {
- elfcpp::Sym_write<size, big_endian> osym(ov);
-
- gold_assert(isym.get_st_name() < strtab_size);
- const char* name = pnames + isym.get_st_name();
- osym.put_st_name(sympool->get_offset(name));
- osym.put_st_value(this->local_values_[i].value(this, 0));
- osym.put_st_size(isym.get_st_size());
- osym.put_st_info(isym.get_st_info());
- osym.put_st_other(isym.get_st_other());
- osym.put_st_shndx(st_shndx);
-
- ov += sym_size;
- }
+ {
+ elfcpp::Sym_write<size, big_endian> osym(ov);
+
+ gold_assert(isym.get_st_name() < strtab_size);
+ const char* name = pnames + isym.get_st_name();
+ osym.put_st_name(sympool->get_offset(name));
+ osym.put_st_value(this->local_values_[i].value(this, 0));
+ osym.put_st_size(isym.get_st_size());
+ osym.put_st_info(isym.get_st_info());
+ osym.put_st_other(isym.get_st_other());
+ osym.put_st_shndx(st_shndx);
+
+ ov += sym_size;
+ }
// Write the symbol to the output dynamic symbol table.
if (lv.has_output_dynsym_entry())
- {
- gold_assert(dyn_ov < dyn_oview + dyn_output_size);
- elfcpp::Sym_write<size, big_endian> osym(dyn_ov);
-
- gold_assert(isym.get_st_name() < strtab_size);
- const char* name = pnames + isym.get_st_name();
- osym.put_st_name(dynpool->get_offset(name));
- osym.put_st_value(this->local_values_[i].value(this, 0));
- osym.put_st_size(isym.get_st_size());
- osym.put_st_info(isym.get_st_info());
- osym.put_st_other(isym.get_st_other());
- osym.put_st_shndx(st_shndx);
-
- dyn_ov += sym_size;
- }
+ {
+ gold_assert(dyn_ov < dyn_oview + dyn_output_size);
+ elfcpp::Sym_write<size, big_endian> osym(dyn_ov);
+
+ gold_assert(isym.get_st_name() < strtab_size);
+ const char* name = pnames + isym.get_st_name();
+ osym.put_st_name(dynpool->get_offset(name));
+ osym.put_st_value(this->local_values_[i].value(this, 0));
+ osym.put_st_size(isym.get_st_size());
+ osym.put_st_info(isym.get_st_info());
+ osym.put_st_other(isym.get_st_other());
+ osym.put_st_shndx(st_shndx);
+
+ dyn_ov += sym_size;
+ }
}
@@ -2426,7 +2537,7 @@ Sized_relobj_file<size, big_endian>::write_local_symbols(
{
gold_assert(dyn_ov - dyn_oview == dyn_output_size);
of->write_output_view(this->local_dynsym_offset_, dyn_output_size,
- dyn_oview);
+ dyn_oview);
}
}
@@ -2481,26 +2592,26 @@ Sized_relobj_file<size, big_endian>::get_symbol_location_info(
&& static_cast<off_t>(sym.get_st_value()) <= offset
&& (static_cast<off_t>(sym.get_st_value() + sym.get_st_size())
> offset))
- {
- if (sym.get_st_name() > names_size)
+ {
+ if (sym.get_st_name() > names_size)
info->enclosing_symbol_name = "(invalid)";
else
- {
- info->enclosing_symbol_name = symbol_names + sym.get_st_name();
- if (parameters->options().do_demangle())
- {
- char* demangled_name = cplus_demangle(
- info->enclosing_symbol_name.c_str(),
- DMGL_ANSI | DMGL_PARAMS);
- if (demangled_name != NULL)
- {
- info->enclosing_symbol_name.assign(demangled_name);
- free(demangled_name);
- }
- }
- }
+ {
+ info->enclosing_symbol_name = symbol_names + sym.get_st_name();
+ if (parameters->options().do_demangle())
+ {
+ char* demangled_name = cplus_demangle(
+ info->enclosing_symbol_name.c_str(),
+ DMGL_ANSI | DMGL_PARAMS);
+ if (demangled_name != NULL)
+ {
+ info->enclosing_symbol_name.assign(demangled_name);
+ free(demangled_name);
+ }
+ }
+ }
return true;
- }
+ }
}
return false;
@@ -2556,6 +2667,85 @@ Sized_relobj_file<size, big_endian>::do_get_global_symbol_counts(
*used = count;
}
+// Return a view of the decompressed contents of a section. Set *PLEN
+// to the size. Set *IS_NEW to true if the contents need to be freed
+// by the caller.
+
+template<int size, bool big_endian>
+const unsigned char*
+Sized_relobj_file<size, big_endian>::do_decompressed_section_contents(
+ unsigned int shndx,
+ section_size_type* plen,
+ bool* is_new)
+{
+ section_size_type buffer_size;
+ const unsigned char* buffer = this->do_section_contents(shndx, &buffer_size,
+ false);
+
+ if (this->compressed_sections_ == NULL)
+ {
+ *plen = buffer_size;
+ *is_new = false;
+ return buffer;
+ }
+
+ Compressed_section_map::const_iterator p =
+ this->compressed_sections_->find(shndx);
+ if (p == this->compressed_sections_->end())
+ {
+ *plen = buffer_size;
+ *is_new = false;
+ return buffer;
+ }
+
+ section_size_type uncompressed_size = p->second.size;
+ if (p->second.contents != NULL)
+ {
+ *plen = uncompressed_size;
+ *is_new = false;
+ return p->second.contents;
+ }
+
+ unsigned char* uncompressed_data = new unsigned char[uncompressed_size];
+ if (!decompress_input_section(buffer,
+ buffer_size,
+ uncompressed_data,
+ uncompressed_size))
+ this->error(_("could not decompress section %s"),
+ this->do_section_name(shndx).c_str());
+
+ // We could cache the results in p->second.contents and store
+ // false in *IS_NEW, but build_compressed_section_map() would
+ // have done so if it had expected it to be profitable. If
+ // we reach this point, we expect to need the contents only
+ // once in this pass.
+ *plen = uncompressed_size;
+ *is_new = true;
+ return uncompressed_data;
+}
+
+// Discard any buffers of uncompressed sections. This is done
+// at the end of the Add_symbols task.
+
+template<int size, bool big_endian>
+void
+Sized_relobj_file<size, big_endian>::do_discard_decompressed_sections()
+{
+ if (this->compressed_sections_ == NULL)
+ return;
+
+ for (Compressed_section_map::iterator p = this->compressed_sections_->begin();
+ p != this->compressed_sections_->end();
+ ++p)
+ {
+ if (p->second.contents != NULL)
+ {
+ delete[] p->second.contents;
+ p->second.contents = NULL;
+ }
+ }
+}
+
// Input_objects methods.
// Add a regular relocatable object to the list. Return false if this
@@ -2745,7 +2935,8 @@ make_elf_sized_object(const std::string& name, Input_file* input_file,
off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr,
bool* punconfigured)
{
- Target* target = select_target(ehdr.get_e_machine(), size, big_endian,
+ Target* target = select_target(input_file, offset,
+ ehdr.get_e_machine(), size, big_endian,
ehdr.get_e_ident()[elfcpp::EI_OSABI],
ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]);
if (target == NULL)
@@ -2805,7 +2996,7 @@ make_elf_object(const std::string& name, Input_file* input_file, off_t offset,
bool big_endian = false;
int size = 0;
if (!elfcpp::Elf_recognizer::is_valid_header(p, bytes, &size,
- &big_endian, &error))
+ &big_endian, &error))
{
gold_error(_("%s: %s"), name.c_str(), error.c_str());
return NULL;
diff --git a/binutils-2.22/gold/object.h b/binutils-2.22/gold/object.h
index a389c54..5c70a0c 100644
--- a/binutils-2.22/gold/object.h
+++ b/binutils-2.22/gold/object.h
@@ -1,6 +1,7 @@
// object.h -- support for an object file for linking in gold -*- C++ -*-
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -47,7 +48,7 @@ class Pluginobj;
class Dynobj;
class Object_merge_map;
class Relocatable_relocs;
-class Symbols_data;
+struct Symbols_data;
template<typename Stringpool_char>
class Stringpool_template;
@@ -725,6 +726,20 @@ class Object
section_size_type* uncompressed_size) const
{ return this->do_section_is_compressed(shndx, uncompressed_size); }
+ // Return a view of the decompressed contents of a section. Set *PLEN
+ // to the size. Set *IS_NEW to true if the contents need to be freed
+ // by the caller.
+ const unsigned char*
+ decompressed_section_contents(unsigned int shndx, section_size_type* plen,
+ bool* is_cached)
+ { return this->do_decompressed_section_contents(shndx, plen, is_cached); }
+
+ // Discard any buffers of decompressed sections. This is done
+ // at the end of the Add_symbols task.
+ void
+ discard_decompressed_sections()
+ { this->do_discard_decompressed_sections(); }
+
// Return the index of the first incremental relocation for symbol SYMNDX.
unsigned int
get_incremental_reloc_base(unsigned int symndx) const
@@ -791,8 +806,9 @@ class Object
// Return the location of the contents of a section. Implemented by
// child class.
- virtual Location
- do_section_contents(unsigned int shndx) = 0;
+ virtual const unsigned char*
+ do_section_contents(unsigned int shndx, section_size_type* plen,
+ bool cache) = 0;
// Get the size of a section--implemented by child class.
virtual uint64_t
@@ -892,6 +908,27 @@ class Object
do_section_is_compressed(unsigned int, section_size_type*) const
{ return false; }
+ // Return a view of the decompressed contents of a section. Set *PLEN
+ // to the size. This default implementation simply returns the
+ // raw section contents and sets *IS_NEW to false to indicate
+ // that the contents do not need to be freed by the caller.
+ // This function must be overridden for any types of object files
+ // that might contain compressed sections.
+ virtual const unsigned char*
+ do_decompressed_section_contents(unsigned int shndx,
+ section_size_type* plen,
+ bool* is_new)
+ {
+ *is_new = false;
+ return this->do_section_contents(shndx, plen, false);
+ }
+
+ // Discard any buffers of decompressed sections. This is done
+ // at the end of the Add_symbols task.
+ virtual void
+ do_discard_decompressed_sections()
+ { }
+
// Return the index of the first incremental relocation for symbol SYMNDX--
// implemented by child class.
virtual unsigned int
@@ -1009,6 +1046,39 @@ class Relobj : public Object
scan_relocs(Symbol_table* symtab, Layout* layout, Read_relocs_data* rd)
{ return this->do_scan_relocs(symtab, layout, rd); }
+ // Return the value of the local symbol whose index is SYMNDX, plus
+ // ADDEND. ADDEND is passed in so that we can correctly handle the
+ // section symbol for a merge section.
+ uint64_t
+ local_symbol_value(unsigned int symndx, uint64_t addend) const
+ { return this->do_local_symbol_value(symndx, addend); }
+
+ // Return the PLT offset for a local symbol. It is an error to call
+ // this if it doesn't have one.
+ unsigned int
+ local_plt_offset(unsigned int symndx) const
+ { return this->do_local_plt_offset(symndx); }
+
+ // Return whether the local symbol SYMNDX has a GOT offset of type
+ // GOT_TYPE.
+ bool
+ local_has_got_offset(unsigned int symndx, unsigned int got_type) const
+ { return this->do_local_has_got_offset(symndx, got_type); }
+
+ // Return the GOT offset of type GOT_TYPE of the local symbol
+ // SYMNDX. It is an error to call this if the symbol does not have
+ // a GOT offset of the specified type.
+ unsigned int
+ local_got_offset(unsigned int symndx, unsigned int got_type) const
+ { return this->do_local_got_offset(symndx, got_type); }
+
+ // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
+ // to GOT_OFFSET.
+ void
+ set_local_got_offset(unsigned int symndx, unsigned int got_type,
+ unsigned int got_offset)
+ { this->do_set_local_got_offset(symndx, got_type, got_offset); }
+
// The number of local symbols in the input symbol table.
virtual unsigned int
local_symbol_count() const
@@ -1167,6 +1237,28 @@ class Relobj : public Object
virtual void
do_scan_relocs(Symbol_table*, Layout*, Read_relocs_data*) = 0;
+ // Return the value of a local symbol.
+ virtual uint64_t
+ do_local_symbol_value(unsigned int symndx, uint64_t addend) const = 0;
+
+ // Return the PLT offset of a local symbol.
+ virtual unsigned int
+ do_local_plt_offset(unsigned int symndx) const = 0;
+
+ // Return whether a local symbol has a GOT offset of a given type.
+ virtual bool
+ do_local_has_got_offset(unsigned int symndx,
+ unsigned int got_type) const = 0;
+
+ // Return the GOT offset of a given type of a local symbol.
+ virtual unsigned int
+ do_local_got_offset(unsigned int symndx, unsigned int got_type) const = 0;
+
+ // Set the GOT offset with a given type for a local symbol.
+ virtual void
+ do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
+ unsigned int got_offset) = 0;
+
// Return the number of local symbols--implemented by child class.
virtual unsigned int
do_local_symbol_count() const = 0;
@@ -1720,9 +1812,14 @@ class Reloc_symbol_changes
std::vector<Symbol*> vec_;
};
-// Type for mapping section index to uncompressed size.
+// Type for mapping section index to uncompressed size and contents.
-typedef std::map<unsigned int, section_size_type> Compressed_section_map;
+struct Compressed_section_info
+{
+ section_size_type size;
+ const unsigned char* contents;
+};
+typedef std::map<unsigned int, Compressed_section_info> Compressed_section_map;
// Abstract base class for a regular object file, either a real object file
// or an incremental (unchanged) object. This is size and endian specific.
@@ -1775,47 +1872,6 @@ class Sized_relobj : public Relobj
return this->section_offsets_[shndx];
}
- // Return whether the local symbol SYMNDX has a GOT offset.
- // For TLS symbols, the GOT entry will hold its tp-relative offset.
- bool
- local_has_got_offset(unsigned int symndx, unsigned int got_type) const
- {
- Local_got_offsets::const_iterator p =
- this->local_got_offsets_.find(symndx);
- return (p != this->local_got_offsets_.end()
- && p->second->get_offset(got_type) != -1U);
- }
-
- // Return the GOT offset of the local symbol SYMNDX.
- unsigned int
- local_got_offset(unsigned int symndx, unsigned int got_type) const
- {
- Local_got_offsets::const_iterator p =
- this->local_got_offsets_.find(symndx);
- gold_assert(p != this->local_got_offsets_.end());
- unsigned int off = p->second->get_offset(got_type);
- gold_assert(off != -1U);
- return off;
- }
-
- // Set the GOT offset of the local symbol SYMNDX to GOT_OFFSET.
- void
- set_local_got_offset(unsigned int symndx, unsigned int got_type,
- unsigned int got_offset)
- {
- Local_got_offsets::const_iterator p =
- this->local_got_offsets_.find(symndx);
- if (p != this->local_got_offsets_.end())
- p->second->set_offset(got_type, got_offset);
- else
- {
- Got_offset_list* g = new Got_offset_list(got_type, got_offset);
- std::pair<Local_got_offsets::iterator, bool> ins =
- this->local_got_offsets_.insert(std::make_pair(symndx, g));
- gold_assert(ins.second);
- }
- }
-
// Iterate over local symbols, calling a visitor class V for each GOT offset
// associated with a local symbol.
void
@@ -1855,6 +1911,49 @@ class Sized_relobj : public Relobj
: convert_types<Address, uint64_t>(off));
}
+ // Return whether the local symbol SYMNDX has a GOT offset of type
+ // GOT_TYPE.
+ bool
+ do_local_has_got_offset(unsigned int symndx, unsigned int got_type) const
+ {
+ Local_got_offsets::const_iterator p =
+ this->local_got_offsets_.find(symndx);
+ return (p != this->local_got_offsets_.end()
+ && p->second->get_offset(got_type) != -1U);
+ }
+
+ // Return the GOT offset of type GOT_TYPE of the local symbol
+ // SYMNDX.
+ unsigned int
+ do_local_got_offset(unsigned int symndx, unsigned int got_type) const
+ {
+ Local_got_offsets::const_iterator p =
+ this->local_got_offsets_.find(symndx);
+ gold_assert(p != this->local_got_offsets_.end());
+ unsigned int off = p->second->get_offset(got_type);
+ gold_assert(off != -1U);
+ return off;
+ }
+
+ // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
+ // to GOT_OFFSET.
+ void
+ do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
+ unsigned int got_offset)
+ {
+ Local_got_offsets::const_iterator p =
+ this->local_got_offsets_.find(symndx);
+ if (p != this->local_got_offsets_.end())
+ p->second->set_offset(got_type, got_offset);
+ else
+ {
+ Got_offset_list* g = new Got_offset_list(got_type, got_offset);
+ std::pair<Local_got_offsets::iterator, bool> ins =
+ this->local_got_offsets_.insert(std::make_pair(symndx, g));
+ gold_assert(ins.second);
+ }
+ }
+
private:
// The GOT offsets of local symbols. This map also stores GOT offsets
// for tp-relative offsets for TLS symbols.
@@ -2000,11 +2099,6 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
bool
local_has_plt_offset(unsigned int symndx) const;
- // Return the PLT offset for a local symbol. It is an error to call
- // this if it doesn't have one.
- unsigned int
- local_plt_offset(unsigned int symndx) const;
-
// Set the PLT offset of the local symbol SYMNDX.
void
set_local_plt_offset(unsigned int symndx, unsigned int plt_offset);
@@ -2050,6 +2144,19 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
void
do_read_symbols(Read_symbols_data*);
+ // Return the value of a local symbol.
+ uint64_t
+ do_local_symbol_value(unsigned int symndx, uint64_t addend) const
+ {
+ const Symbol_value<size>* symval = this->local_symbol(symndx);
+ return symval->value(this, addend);
+ }
+
+ // Return the PLT offset for a local symbol. It is an error to call
+ // this if it doesn't have one.
+ unsigned int
+ do_local_plt_offset(unsigned int symndx) const;
+
// Return the number of local symbols.
unsigned int
do_local_symbol_count() const
@@ -2132,9 +2239,19 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
{ return this->elf_file_.section_name(shndx); }
// Return the location of the contents of a section.
- Object::Location
- do_section_contents(unsigned int shndx)
- { return this->elf_file_.section_contents(shndx); }
+ const unsigned char*
+ do_section_contents(unsigned int shndx, section_size_type* plen,
+ bool cache)
+ {
+ Object::Location loc(this->elf_file_.section_contents(shndx));
+ *plen = convert_to_section_size_type(loc.data_size);
+ if (*plen == 0)
+ {
+ static const unsigned char empty[1] = { '\0' };
+ return empty;
+ }
+ return this->get_view(loc.file_offset, *plen, true, cache);
+ }
// Return section flags.
uint64_t
@@ -2254,12 +2371,25 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
if (p != this->compressed_sections_->end())
{
if (uncompressed_size != NULL)
- *uncompressed_size = p->second;
+ *uncompressed_size = p->second.size;
return true;
}
return false;
}
+ // Return a view of the uncompressed contents of a section. Set *PLEN
+ // to the size. Set *IS_NEW to true if the contents need to be deleted
+ // by the caller.
+ const unsigned char*
+ do_decompressed_section_contents(unsigned int shndx,
+ section_size_type* plen,
+ bool* is_new);
+
+ // Discard any buffers of decompressed sections. This is done
+ // at the end of the Add_symbols task.
+ void
+ do_discard_decompressed_sections();
+
private:
// For convenience.
typedef Sized_relobj_file<size, big_endian> This;
@@ -2544,7 +2674,8 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
std::vector<Deferred_layout> deferred_layout_;
// The list of relocation sections whose layout was deferred.
std::vector<Deferred_layout> deferred_layout_relocs_;
- // For compressed debug sections, map section index to uncompressed size.
+ // For compressed debug sections, map section index to uncompressed size
+ // and contents.
Compressed_section_map* compressed_sections_;
};
diff --git a/binutils-2.22/gold/options.cc b/binutils-2.22/gold/options.cc
index 66c7f68..fe9a00e 100644
--- a/binutils-2.22/gold/options.cc
+++ b/binutils-2.22/gold/options.cc
@@ -1121,33 +1121,48 @@ General_options::finalize()
program_name);
#endif
+ std::string libpath;
if (this->user_set_Y())
{
- std::string s = this->Y();
- if (s.compare(0, 2, "P,") == 0)
- s.erase(0, 2);
+ libpath = this->Y();
+ if (libpath.compare(0, 2, "P,") == 0)
+ libpath.erase(0, 2);
+ }
+ else if (!this->nostdlib())
+ {
+#ifndef NATIVE_LINKER
+#define NATIVE_LINKER 0
+#endif
+ const char* p = LIB_PATH;
+ if (strcmp(p, "::DEFAULT::") != 0)
+ libpath = p;
+ else if (NATIVE_LINKER
+ || this->user_set_sysroot()
+ || *TARGET_SYSTEM_ROOT != '\0')
+ {
+ this->add_to_library_path_with_sysroot("/lib");
+ this->add_to_library_path_with_sysroot("/usr/lib");
+ }
+ else
+ this->add_to_library_path_with_sysroot(TOOLLIBDIR);
+ }
+ if (!libpath.empty())
+ {
size_t pos = 0;
size_t next_pos;
do
{
- next_pos = s.find(':', pos);
+ next_pos = libpath.find(':', pos);
size_t len = (next_pos == std::string::npos
? next_pos
: next_pos - pos);
if (len != 0)
- this->add_to_library_path_with_sysroot(s.substr(pos, len).c_str());
+ this->add_to_library_path_with_sysroot(libpath.substr(pos, len));
pos = next_pos + 1;
}
while (next_pos != std::string::npos);
}
- else if (!this->nostdlib())
- {
- // Even if they don't specify it, we add -L /lib and -L /usr/lib.
- // FIXME: We should only do this when configured in native mode.
- this->add_to_library_path_with_sysroot("/lib");
- this->add_to_library_path_with_sysroot("/usr/lib");
- }
// Parse the contents of -retain-symbols-file into a set.
if (this->retain_symbols_file())
@@ -1188,6 +1203,8 @@ General_options::finalize()
gold_fatal(_("-shared and -static are incompatible"));
if (this->shared() && this->pie())
gold_fatal(_("-shared and -pie are incompatible"));
+ if (this->pie() && this->is_static())
+ gold_fatal(_("-pie and -static are incompatible"));
if (this->shared() && this->relocatable())
gold_fatal(_("-shared and -r are incompatible"));
@@ -1224,6 +1241,37 @@ General_options::finalize()
gold_fatal(_("Options --incremental-changed, --incremental-unchanged, "
"--incremental-unknown require the use of --incremental"));
+ // Check for options that are not compatible with incremental linking.
+ // Where an option can be disabled without seriously changing the semantics
+ // of the link, we turn the option off; otherwise, we issue a fatal error.
+
+ if (this->incremental_mode_ != INCREMENTAL_OFF)
+ {
+ if (this->relocatable())
+ gold_fatal(_("incremental linking is not compatible with -r"));
+ if (this->emit_relocs())
+ gold_fatal(_("incremental linking is not compatible with "
+ "--emit-relocs"));
+ if (this->has_plugins())
+ gold_fatal(_("incremental linking is not compatible with --plugin"));
+ if (this->gc_sections())
+ {
+ gold_warning(_("ignoring --gc-sections for an incremental link"));
+ this->set_gc_sections(false);
+ }
+ if (this->icf_enabled())
+ {
+ gold_warning(_("ignoring --icf for an incremental link"));
+ this->set_icf_status(ICF_NONE);
+ }
+ if (strcmp(this->compress_debug_sections(), "none") != 0)
+ {
+ gold_warning(_("ignoring --compress-debug-sections for an "
+ "incremental link"));
+ this->set_compress_debug_sections("none");
+ }
+ }
+
// FIXME: we can/should be doing a lot more sanity checking here.
}
diff --git a/binutils-2.22/gold/options.h b/binutils-2.22/gold/options.h
index 768df9c..50762a5 100644
--- a/binutils-2.22/gold/options.h
+++ b/binutils-2.22/gold/options.h
@@ -543,7 +543,7 @@ class Search_directory
{ }
// This is the usual constructor.
- Search_directory(const char* name, bool put_in_sysroot)
+ Search_directory(const std::string& name, bool put_in_sysroot)
: name_(name), put_in_sysroot_(put_in_sysroot), is_in_sysroot_(false)
{
if (this->name_.empty())
@@ -739,6 +739,9 @@ class General_options
N_("Export all dynamic symbols"),
N_("Do not export all dynamic symbols (default)"));
+ DEFINE_set(export_dynamic_symbol, options::TWO_DASHES, '\0',
+ N_("Export SYMBOL to dynamic symbol table"), N_("SYMBOL"));
+
DEFINE_special(EB, options::ONE_DASH, '\0',
N_("Link big-endian objects."), NULL);
@@ -791,6 +794,14 @@ class General_options
DEFINE_bool(g, options::EXACTLY_ONE_DASH, '\0', false,
N_("Ignored"), NULL);
+ DEFINE_bool(gdb_index, options::TWO_DASHES, '\0', false,
+ N_("Generate .gdb_index section"),
+ N_("Do not generate .gdb_index section"));
+
+ DEFINE_bool(gnu_unique, options::TWO_DASHES, '\0', true,
+ N_("Enable STB_GNU_UNIQUE symbol binding (default)"),
+ N_("Disable STB_GNU_UNIQUE symbol binding"));
+
DEFINE_string(soname, options::ONE_DASH, 'h', NULL,
N_("Set shared library name"), N_("FILENAME"));
@@ -878,6 +889,10 @@ class General_options
DEFINE_string(m, options::EXACTLY_ONE_DASH, 'm', "",
N_("Set GNU linker emulation; obsolete"), N_("EMULATION"));
+ DEFINE_bool(mmap_output_file, options::TWO_DASHES, '\0', true,
+ N_("Map the output file for writing (default)."),
+ N_("Do not map the output file for writing."));
+
DEFINE_bool(print_map, options::TWO_DASHES, 'M', false,
N_("Write map file on standard output"), NULL);
DEFINE_string(Map, options::ONE_DASH, '\0', NULL, N_("Write map file"),
@@ -928,6 +943,11 @@ class General_options
N_("Pass an option to the plugin"), N_("OPTION"));
#endif
+ DEFINE_bool(posix_fallocate, options::TWO_DASHES, '\0', true,
+ N_("Use posix_fallocate to reserve space in the output file"
+ " (default)."),
+ N_("Use fallocate or ftruncate to reserve space."));
+
DEFINE_bool(preread_archive_symbols, options::TWO_DASHES, '\0', false,
N_("Preread archive symbols when multi-threaded"), NULL);
@@ -991,7 +1011,7 @@ class General_options
N_("Emit only debug line number information"), NULL);
DEFINE_bool(strip_debug_gdb, options::TWO_DASHES, '\0', false,
N_("Strip debug symbols that are unused by gdb "
- "(at least versions <= 6.7)"), NULL);
+ "(at least versions <= 7.4)"), NULL);
DEFINE_bool(strip_lto_sections, options::TWO_DASHES, '\0', true,
N_("Strip LTO intermediate code sections"), NULL);
@@ -1385,6 +1405,11 @@ class General_options
bool
section_start(const char* secname, uint64_t* paddr) const;
+ // Return whether any --section-start option was used.
+ bool
+ any_section_start() const
+ { return !this->section_starts_.empty(); }
+
enum Fix_v4bx
{
// Leave original instruction.
@@ -1454,7 +1479,7 @@ class General_options
// These are called by finalize() to set up the search-path correctly.
void
- add_to_library_path_with_sysroot(const char* arg)
+ add_to_library_path_with_sysroot(const std::string& arg)
{ this->add_search_directory_to_library_path(Search_directory(arg, true)); }
// Apply any sysroot to the directory lists.
diff --git a/binutils-2.22/gold/output.cc b/binutils-2.22/gold/output.cc
index 34947d9..99890eb 100644
--- a/binutils-2.22/gold/output.cc
+++ b/binutils-2.22/gold/output.cc
@@ -111,18 +111,6 @@ extern "C" void *gold_mremap(void *, size_t, size_t, int);
# define MREMAP_MAYMOVE 1
#endif
-#ifndef HAVE_POSIX_FALLOCATE
-// A dummy, non general, version of posix_fallocate. Here we just set
-// the file size and hope that there is enough disk space. FIXME: We
-// could allocate disk space by walking block by block and writing a
-// zero byte into each block.
-static int
-posix_fallocate(int o, off_t offset, off_t len)
-{
- return ftruncate(o, offset + len);
-}
-#endif // !defined(HAVE_POSIX_FALLOCATE)
-
// Mingw does not have S_ISLNK.
#ifndef S_ISLNK
# define S_ISLNK(mode) 0
@@ -131,6 +119,27 @@ posix_fallocate(int o, off_t offset, off_t len)
namespace gold
{
+// A wrapper around posix_fallocate. If we don't have posix_fallocate,
+// or the --no-posix-fallocate option is set, we try the fallocate
+// system call directly. If that fails, we use ftruncate to set
+// the file size and hope that there is enough disk space.
+
+static int
+gold_fallocate(int o, off_t offset, off_t len)
+{
+#ifdef HAVE_POSIX_FALLOCATE
+ if (parameters->options().posix_fallocate())
+ return ::posix_fallocate(o, offset, len);
+#endif // defined(HAVE_POSIX_FALLOCATE)
+#ifdef HAVE_FALLOCATE
+ if (::fallocate(o, 0, offset, len) == 0)
+ return 0;
+#endif // defined(HAVE_FALLOCATE)
+ if (::ftruncate(o, offset + len) < 0)
+ return errno;
+ return 0;
+}
+
// Output_data variables.
bool Output_data::allocated_sizes_are_fixed;
@@ -703,10 +712,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
Output_data* od,
Address address,
bool is_relative,
- bool is_symbolless)
+ bool is_symbolless,
+ bool use_plt_offset)
: address_(address), local_sym_index_(GSYM_CODE), type_(type),
is_relative_(is_relative), is_symbolless_(is_symbolless),
- is_section_symbol_(false), shndx_(INVALID_CODE)
+ is_section_symbol_(false), use_plt_offset_(use_plt_offset), shndx_(INVALID_CODE)
{
// this->type_ is a bitfield; make sure TYPE fits.
gold_assert(this->type_ == type);
@@ -724,10 +734,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
unsigned int shndx,
Address address,
bool is_relative,
- bool is_symbolless)
+ bool is_symbolless,
+ bool use_plt_offset)
: address_(address), local_sym_index_(GSYM_CODE), type_(type),
is_relative_(is_relative), is_symbolless_(is_symbolless),
- is_section_symbol_(false), shndx_(shndx)
+ is_section_symbol_(false), use_plt_offset_(use_plt_offset), shndx_(shndx)
{
gold_assert(shndx != INVALID_CODE);
// this->type_ is a bitfield; make sure TYPE fits.
@@ -749,10 +760,12 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
Address address,
bool is_relative,
bool is_symbolless,
- bool is_section_symbol)
+ bool is_section_symbol,
+ bool use_plt_offset)
: address_(address), local_sym_index_(local_sym_index), type_(type),
is_relative_(is_relative), is_symbolless_(is_symbolless),
- is_section_symbol_(is_section_symbol), shndx_(INVALID_CODE)
+ is_section_symbol_(is_section_symbol), use_plt_offset_(use_plt_offset),
+ shndx_(INVALID_CODE)
{
gold_assert(local_sym_index != GSYM_CODE
&& local_sym_index != INVALID_CODE);
@@ -773,10 +786,12 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
Address address,
bool is_relative,
bool is_symbolless,
- bool is_section_symbol)
+ bool is_section_symbol,
+ bool use_plt_offset)
: address_(address), local_sym_index_(local_sym_index), type_(type),
is_relative_(is_relative), is_symbolless_(is_symbolless),
- is_section_symbol_(is_section_symbol), shndx_(shndx)
+ is_section_symbol_(is_section_symbol), use_plt_offset_(use_plt_offset),
+ shndx_(shndx)
{
gold_assert(local_sym_index != GSYM_CODE
&& local_sym_index != INVALID_CODE);
@@ -799,7 +814,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
Address address)
: address_(address), local_sym_index_(SECTION_CODE), type_(type),
is_relative_(false), is_symbolless_(false),
- is_section_symbol_(true), shndx_(INVALID_CODE)
+ is_section_symbol_(true), use_plt_offset_(false), shndx_(INVALID_CODE)
{
// this->type_ is a bitfield; make sure TYPE fits.
gold_assert(this->type_ == type);
@@ -820,7 +835,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
Address address)
: address_(address), local_sym_index_(SECTION_CODE), type_(type),
is_relative_(false), is_symbolless_(false),
- is_section_symbol_(true), shndx_(shndx)
+ is_section_symbol_(true), use_plt_offset_(false), shndx_(shndx)
{
gold_assert(shndx != INVALID_CODE);
// this->type_ is a bitfield; make sure TYPE fits.
@@ -842,7 +857,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
Address address)
: address_(address), local_sym_index_(0), type_(type),
is_relative_(false), is_symbolless_(false),
- is_section_symbol_(false), shndx_(INVALID_CODE)
+ is_section_symbol_(false), use_plt_offset_(false), shndx_(INVALID_CODE)
{
// this->type_ is a bitfield; make sure TYPE fits.
gold_assert(this->type_ == type);
@@ -858,7 +873,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
Address address)
: address_(address), local_sym_index_(0), type_(type),
is_relative_(false), is_symbolless_(false),
- is_section_symbol_(false), shndx_(shndx)
+ is_section_symbol_(false), use_plt_offset_(false), shndx_(shndx)
{
gold_assert(shndx != INVALID_CODE);
// this->type_ is a bitfield; make sure TYPE fits.
@@ -877,7 +892,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
Address address)
: address_(address), local_sym_index_(TARGET_CODE), type_(type),
is_relative_(false), is_symbolless_(false),
- is_section_symbol_(false), shndx_(INVALID_CODE)
+ is_section_symbol_(false), use_plt_offset_(false), shndx_(INVALID_CODE)
{
// this->type_ is a bitfield; make sure TYPE fits.
gold_assert(this->type_ == type);
@@ -894,7 +909,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
Address address)
: address_(address), local_sym_index_(TARGET_CODE), type_(type),
is_relative_(false), is_symbolless_(false),
- is_section_symbol_(false), shndx_(shndx)
+ is_section_symbol_(false), use_plt_offset_(false), shndx_(shndx)
{
gold_assert(shndx != INVALID_CODE);
// this->type_ is a bitfield; make sure TYPE fits.
@@ -1110,7 +1125,14 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::symbol_value(
{
const Sized_symbol<size>* sym;
sym = static_cast<const Sized_symbol<size>*>(this->u1_.gsym);
- return sym->value() + addend;
+ if (this->use_plt_offset_ && sym->has_plt_offset())
+ {
+ uint64_t plt_address =
+ parameters->target().plt_address_for_global(sym);
+ return plt_address + sym->plt_offset();
+ }
+ else
+ return sym->value() + addend;
}
gold_assert(this->local_sym_index_ != SECTION_CODE
&& this->local_sym_index_ != TARGET_CODE
@@ -1121,6 +1143,12 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::symbol_value(
Sized_relobj_file<size, big_endian>* relobj =
this->u1_.relobj->sized_relobj();
gold_assert(relobj != NULL);
+ if (this->use_plt_offset_)
+ {
+ uint64_t plt_address =
+ parameters->target().plt_address_for_local(relobj, lsi);
+ return plt_address + relobj->local_plt_offset(lsi);
+ }
const Symbol_value<size>* symval = relobj->local_symbol(lsi);
return symval->value(relobj, addend);
}
@@ -1375,11 +1403,13 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
default:
{
- const Sized_relobj_file<size, big_endian>* object = this->u_.object;
+ const Relobj* object = this->u_.object;
const unsigned int lsi = this->local_sym_index_;
- const Symbol_value<size>* symval = object->local_symbol(lsi);
if (!this->use_plt_offset_)
- val = symval->value(this->u_.object, 0);
+ {
+ uint64_t lval = object->local_symbol_value(lsi, 0);
+ val = convert_types<Valtype, uint64_t>(lval);
+ }
else
{
uint64_t plt_address =
@@ -1436,23 +1466,7 @@ void
Output_data_got<size, big_endian>::add_global_with_rel(
Symbol* gsym,
unsigned int got_type,
- Rel_dyn* rel_dyn,
- unsigned int r_type)
-{
- if (gsym->has_got_offset(got_type))
- return;
-
- unsigned int got_offset = this->add_got_entry(Got_entry());
- gsym->set_got_offset(got_type, got_offset);
- rel_dyn->add_global(gsym, r_type, this, got_offset);
-}
-
-template<int size, bool big_endian>
-void
-Output_data_got<size, big_endian>::add_global_with_rela(
- Symbol* gsym,
- unsigned int got_type,
- Rela_dyn* rela_dyn,
+ Output_data_reloc_generic* rel_dyn,
unsigned int r_type)
{
if (gsym->has_got_offset(got_type))
@@ -1460,7 +1474,7 @@ Output_data_got<size, big_endian>::add_global_with_rela(
unsigned int got_offset = this->add_got_entry(Got_entry());
gsym->set_got_offset(got_type, got_offset);
- rela_dyn->add_global(gsym, r_type, this, got_offset, 0);
+ rel_dyn->add_global_generic(gsym, r_type, this, got_offset, 0);
}
// Add a pair of entries for a global symbol to the GOT, and add
@@ -1471,27 +1485,7 @@ void
Output_data_got<size, big_endian>::add_global_pair_with_rel(
Symbol* gsym,
unsigned int got_type,
- Rel_dyn* rel_dyn,
- unsigned int r_type_1,
- unsigned int r_type_2)
-{
- if (gsym->has_got_offset(got_type))
- return;
-
- unsigned int got_offset = this->add_got_entry_pair(Got_entry(), Got_entry());
- gsym->set_got_offset(got_type, got_offset);
- rel_dyn->add_global(gsym, r_type_1, this, got_offset);
-
- if (r_type_2 != 0)
- rel_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8);
-}
-
-template<int size, bool big_endian>
-void
-Output_data_got<size, big_endian>::add_global_pair_with_rela(
- Symbol* gsym,
- unsigned int got_type,
- Rela_dyn* rela_dyn,
+ Output_data_reloc_generic* rel_dyn,
unsigned int r_type_1,
unsigned int r_type_2)
{
@@ -1500,10 +1494,11 @@ Output_data_got<size, big_endian>::add_global_pair_with_rela(
unsigned int got_offset = this->add_got_entry_pair(Got_entry(), Got_entry());
gsym->set_got_offset(got_type, got_offset);
- rela_dyn->add_global(gsym, r_type_1, this, got_offset, 0);
+ rel_dyn->add_global_generic(gsym, r_type_1, this, got_offset, 0);
if (r_type_2 != 0)
- rela_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8, 0);
+ rel_dyn->add_global_generic(gsym, r_type_2, this,
+ got_offset + size / 8, 0);
}
// Add an entry for a local symbol to the GOT. This returns true if
@@ -1513,7 +1508,7 @@ Output_data_got<size, big_endian>::add_global_pair_with_rela(
template<int size, bool big_endian>
bool
Output_data_got<size, big_endian>::add_local(
- Sized_relobj_file<size, big_endian>* object,
+ Relobj* object,
unsigned int symndx,
unsigned int got_type)
{
@@ -1531,7 +1526,7 @@ Output_data_got<size, big_endian>::add_local(
template<int size, bool big_endian>
bool
Output_data_got<size, big_endian>::add_local_plt(
- Sized_relobj_file<size, big_endian>* object,
+ Relobj* object,
unsigned int symndx,
unsigned int got_type)
{
@@ -1550,10 +1545,10 @@ Output_data_got<size, big_endian>::add_local_plt(
template<int size, bool big_endian>
void
Output_data_got<size, big_endian>::add_local_with_rel(
- Sized_relobj_file<size, big_endian>* object,
+ Relobj* object,
unsigned int symndx,
unsigned int got_type,
- Rel_dyn* rel_dyn,
+ Output_data_reloc_generic* rel_dyn,
unsigned int r_type)
{
if (object->local_has_got_offset(symndx, got_type))
@@ -1561,24 +1556,7 @@ Output_data_got<size, big_endian>::add_local_with_rel(
unsigned int got_offset = this->add_got_entry(Got_entry());
object->set_local_got_offset(symndx, got_type, got_offset);
- rel_dyn->add_local(object, symndx, r_type, this, got_offset);
-}
-
-template<int size, bool big_endian>
-void
-Output_data_got<size, big_endian>::add_local_with_rela(
- Sized_relobj_file<size, big_endian>* object,
- unsigned int symndx,
- unsigned int got_type,
- Rela_dyn* rela_dyn,
- unsigned int r_type)
-{
- if (object->local_has_got_offset(symndx, got_type))
- return;
-
- unsigned int got_offset = this->add_got_entry(Got_entry());
- object->set_local_got_offset(symndx, got_type, got_offset);
- rela_dyn->add_local(object, symndx, r_type, this, got_offset, 0);
+ rel_dyn->add_local_generic(object, symndx, r_type, this, got_offset, 0);
}
// Add a pair of entries for a local symbol to the GOT, and add
@@ -1587,36 +1565,11 @@ Output_data_got<size, big_endian>::add_local_with_rela(
template<int size, bool big_endian>
void
Output_data_got<size, big_endian>::add_local_pair_with_rel(
- Sized_relobj_file<size, big_endian>* object,
- unsigned int symndx,
- unsigned int shndx,
- unsigned int got_type,
- Rel_dyn* rel_dyn,
- unsigned int r_type_1,
- unsigned int r_type_2)
-{
- if (object->local_has_got_offset(symndx, got_type))
- return;
-
- unsigned int got_offset =
- this->add_got_entry_pair(Got_entry(),
- Got_entry(object, symndx, false));
- object->set_local_got_offset(symndx, got_type, got_offset);
- Output_section* os = object->output_section(shndx);
- rel_dyn->add_output_section(os, r_type_1, this, got_offset);
-
- if (r_type_2 != 0)
- rel_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8);
-}
-
-template<int size, bool big_endian>
-void
-Output_data_got<size, big_endian>::add_local_pair_with_rela(
- Sized_relobj_file<size, big_endian>* object,
+ Relobj* object,
unsigned int symndx,
unsigned int shndx,
unsigned int got_type,
- Rela_dyn* rela_dyn,
+ Output_data_reloc_generic* rel_dyn,
unsigned int r_type_1,
unsigned int r_type_2)
{
@@ -1628,10 +1581,11 @@ Output_data_got<size, big_endian>::add_local_pair_with_rela(
Got_entry(object, symndx, false));
object->set_local_got_offset(symndx, got_type, got_offset);
Output_section* os = object->output_section(shndx);
- rela_dyn->add_output_section(os, r_type_1, this, got_offset, 0);
+ rel_dyn->add_output_section_generic(os, r_type_1, this, got_offset, 0);
if (r_type_2 != 0)
- rela_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8, 0);
+ rel_dyn->add_output_section_generic(os, r_type_2, this,
+ got_offset + size / 8, 0);
}
// Reserve a slot in the GOT for a local symbol or the second slot of a pair.
@@ -1640,11 +1594,11 @@ template<int size, bool big_endian>
void
Output_data_got<size, big_endian>::reserve_local(
unsigned int i,
- Sized_relobj<size, big_endian>* object,
+ Relobj* object,
unsigned int sym_index,
unsigned int got_type)
{
- this->reserve_slot(i);
+ this->do_reserve_slot(i);
object->set_local_got_offset(sym_index, got_type, this->got_offset(i));
}
@@ -1657,7 +1611,7 @@ Output_data_got<size, big_endian>::reserve_global(
Symbol* gsym,
unsigned int got_type)
{
- this->reserve_slot(i);
+ this->do_reserve_slot(i);
gsym->set_got_offset(got_type, this->got_offset(i));
}
@@ -1922,7 +1876,7 @@ Output_symtab_xindex::endian_do_write(unsigned char* const oview)
++p)
{
unsigned int symndx = p->first;
- gold_assert(static_cast<off_t>(symndx * 4) < this->data_size());
+ gold_assert(symndx * 4 < this->data_size());
elfcpp::Swap<32, big_endian>::writeval(oview + symndx * 4, p->second);
}
}
@@ -2476,7 +2430,10 @@ Output_section::add_input_section(Layout* layout,
|| layout->is_section_ordering_specified())
{
Input_section isecn(object, shndx, input_section_size, addralign);
- if (layout->is_section_ordering_specified())
+ /* If section ordering is requested by specifying a ordering file,
+ using --section-ordering-file, match the section name with
+ a pattern. */
+ if (parameters->options().section_ordering_file())
{
unsigned int section_order_index =
layout->find_section_order_index(std::string(secname));
@@ -3485,7 +3442,7 @@ Output_section::Input_section_sort_section_order_index_compare::operator()(
void
Output_section::update_section_layout(
- const Section_layout_order& order_map)
+ const Section_layout_order* order_map)
{
for (Input_section_list::iterator p = this->input_sections_.begin();
p != this->input_sections_.end();
@@ -3499,8 +3456,8 @@ Output_section::update_section_layout(
: p->relaxed_input_section()->relobj());
unsigned int shndx = p->shndx();
Section_layout_order::const_iterator it
- = order_map.find(Section_id(obj, shndx));
- if (it == order_map.end())
+ = order_map->find(Section_id(obj, shndx));
+ if (it == order_map->end())
continue;
unsigned int section_order_index = it->second;
if (section_order_index != 0)
@@ -4880,17 +4837,27 @@ Output_file::open_base_file(const char* base_name, bool writable)
if (use_base_file)
{
this->open(s.st_size);
- ssize_t len = ::read(o, this->base_, s.st_size);
- if (len < 0)
- {
- gold_info(_("%s: read failed: %s"), base_name, strerror(errno));
- return false;
- }
- if (len < s.st_size)
- {
- gold_info(_("%s: file too short"), base_name);
- return false;
- }
+ ssize_t bytes_to_read = s.st_size;
+ unsigned char* p = this->base_;
+ while (bytes_to_read > 0)
+ {
+ ssize_t len = ::read(o, p, bytes_to_read);
+ if (len < 0)
+ {
+ gold_info(_("%s: read failed: %s"), base_name, strerror(errno));
+ return false;
+ }
+ if (len == 0)
+ {
+ gold_info(_("%s: file too short: read only %lld of %lld bytes"),
+ base_name,
+ static_cast<long long>(s.st_size - bytes_to_read),
+ static_cast<long long>(s.st_size));
+ return false;
+ }
+ p += len;
+ bytes_to_read -= len;
+ }
::close(o);
return true;
}
@@ -5052,8 +5019,12 @@ Output_file::map_no_anonymous(bool writable)
// output file will wind up incomplete, but we will have already
// exited. The alternative to fallocate would be to use fdatasync,
// but that would be a more significant performance hit.
- if (writable && ::posix_fallocate(o, 0, this->file_size_) < 0)
- gold_fatal(_("%s: %s"), this->name_, strerror(errno));
+ if (writable)
+ {
+ int err = gold_fallocate(o, 0, this->file_size_);
+ if (err != 0)
+ gold_fatal(_("%s: %s"), this->name_, strerror(err));
+ }
// Map the file into memory.
int prot = PROT_READ;
@@ -5077,7 +5048,8 @@ Output_file::map_no_anonymous(bool writable)
void
Output_file::map()
{
- if (this->map_no_anonymous(true))
+ if (parameters->options().mmap_output_file()
+ && this->map_no_anonymous(true))
return;
// The mmap call might fail because of file system issues: the file
diff --git a/binutils-2.22/gold/output.h b/binutils-2.22/gold/output.h
index 1bec2c0..170f0ff 100644
--- a/binutils-2.22/gold/output.h
+++ b/binutils-2.22/gold/output.h
@@ -1021,24 +1021,27 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
// A reloc against a global symbol.
Output_reloc(Symbol* gsym, unsigned int type, Output_data* od,
- Address address, bool is_relative, bool is_symbolless);
+ Address address, bool is_relative, bool is_symbolless,
+ bool use_plt_offset);
Output_reloc(Symbol* gsym, unsigned int type,
Sized_relobj<size, big_endian>* relobj,
unsigned int shndx, Address address, bool is_relative,
- bool is_symbolless);
+ bool is_symbolless, bool use_plt_offset);
// A reloc against a local symbol or local section symbol.
Output_reloc(Sized_relobj<size, big_endian>* relobj,
unsigned int local_sym_index, unsigned int type,
Output_data* od, Address address, bool is_relative,
- bool is_symbolless, bool is_section_symbol);
+ bool is_symbolless, bool is_section_symbol,
+ bool use_plt_offset);
Output_reloc(Sized_relobj<size, big_endian>* relobj,
unsigned int local_sym_index, unsigned int type,
unsigned int shndx, Address address, bool is_relative,
- bool is_symbolless, bool is_section_symbol);
+ bool is_symbolless, bool is_section_symbol,
+ bool use_plt_offset);
// A reloc against the STT_SECTION symbol of an output section.
@@ -1216,7 +1219,7 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
// input file.
unsigned int local_sym_index_;
// The reloc type--a processor specific code.
- unsigned int type_ : 29;
+ unsigned int type_ : 28;
// True if the relocation is a RELATIVE relocation.
bool is_relative_ : 1;
// True if the relocation is one which should not use
@@ -1224,6 +1227,9 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
bool is_symbolless_ : 1;
// True if the relocation is against a section symbol.
bool is_section_symbol_ : 1;
+ // True if the addend should be the PLT offset.
+ // (Used only for RELA, but stored here for space.)
+ bool use_plt_offset_ : 1;
// If the reloc address is an input section in an object, the
// section index. This is INVALID_CODE if the reloc address is
// specified in some other way.
@@ -1249,17 +1255,18 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
Output_reloc(Symbol* gsym, unsigned int type, Output_data* od,
Address address, Addend addend, bool is_relative,
- bool is_symbolless)
- : rel_(gsym, type, od, address, is_relative, is_symbolless),
+ bool is_symbolless, bool use_plt_offset)
+ : rel_(gsym, type, od, address, is_relative, is_symbolless,
+ use_plt_offset),
addend_(addend)
{ }
Output_reloc(Symbol* gsym, unsigned int type,
Sized_relobj<size, big_endian>* relobj,
unsigned int shndx, Address address, Addend addend,
- bool is_relative, bool is_symbolless)
+ bool is_relative, bool is_symbolless, bool use_plt_offset)
: rel_(gsym, type, relobj, shndx, address, is_relative,
- is_symbolless), addend_(addend)
+ is_symbolless, use_plt_offset), addend_(addend)
{ }
// A reloc against a local symbol.
@@ -1268,9 +1275,10 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
unsigned int local_sym_index, unsigned int type,
Output_data* od, Address address,
Addend addend, bool is_relative,
- bool is_symbolless, bool is_section_symbol)
+ bool is_symbolless, bool is_section_symbol,
+ bool use_plt_offset)
: rel_(relobj, local_sym_index, type, od, address, is_relative,
- is_symbolless, is_section_symbol),
+ is_symbolless, is_section_symbol, use_plt_offset),
addend_(addend)
{ }
@@ -1278,9 +1286,10 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
unsigned int local_sym_index, unsigned int type,
unsigned int shndx, Address address,
Addend addend, bool is_relative,
- bool is_symbolless, bool is_section_symbol)
+ bool is_symbolless, bool is_section_symbol,
+ bool use_plt_offset)
: rel_(relobj, local_sym_index, type, shndx, address, is_relative,
- is_symbolless, is_section_symbol),
+ is_symbolless, is_section_symbol, use_plt_offset),
addend_(addend)
{ }
@@ -1389,6 +1398,55 @@ class Output_data_reloc_generic : public Output_section_data_build
sort_relocs() const
{ return this->sort_relocs_; }
+ // Add a reloc of type TYPE against the global symbol GSYM. The
+ // relocation applies to the data at offset ADDRESS within OD.
+ virtual void
+ add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
+ uint64_t address, uint64_t addend) = 0;
+
+ // Add a reloc of type TYPE against the global symbol GSYM. The
+ // relocation applies to data at offset ADDRESS within section SHNDX
+ // of object file RELOBJ. OD is the associated output section.
+ virtual void
+ add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
+ Relobj* relobj, unsigned int shndx, uint64_t address,
+ uint64_t addend) = 0;
+
+ // Add a reloc of type TYPE against the local symbol LOCAL_SYM_INDEX
+ // in RELOBJ. The relocation applies to the data at offset ADDRESS
+ // within OD.
+ virtual void
+ add_local_generic(Relobj* relobj, unsigned int local_sym_index,
+ unsigned int type, Output_data* od, uint64_t address,
+ uint64_t addend) = 0;
+
+ // Add a reloc of type TYPE against the local symbol LOCAL_SYM_INDEX
+ // in RELOBJ. The relocation applies to the data at offset ADDRESS
+ // within section SHNDX of RELOBJ. OD is the associated output
+ // section.
+ virtual void
+ add_local_generic(Relobj* relobj, unsigned int local_sym_index,
+ unsigned int type, Output_data* od, unsigned int shndx,
+ uint64_t address, uint64_t addend) = 0;
+
+ // Add a reloc of type TYPE against the STT_SECTION symbol of the
+ // output section OS. The relocation applies to the data at offset
+ // ADDRESS within OD.
+ virtual void
+ add_output_section_generic(Output_section *os, unsigned int type,
+ Output_data* od, uint64_t address,
+ uint64_t addend) = 0;
+
+ // Add a reloc of type TYPE against the STT_SECTION symbol of the
+ // output section OS. The relocation applies to the data at offset
+ // ADDRESS within section SHNDX of RELOBJ. OD is the associated
+ // output section.
+ virtual void
+ add_output_section_generic(Output_section* os, unsigned int type,
+ Output_data* od, Relobj* relobj,
+ unsigned int shndx, uint64_t address,
+ uint64_t addend) = 0;
+
protected:
// Note that we've added another relative reloc.
void
@@ -1450,7 +1508,8 @@ class Output_data_reloc_base : public Output_data_reloc_generic
{
this->relocs_.push_back(reloc);
this->set_current_data_size(this->relocs_.size() * reloc_size);
- od->add_dynamic_reloc();
+ if (dynamic)
+ od->add_dynamic_reloc();
if (reloc.is_relative())
this->bump_relative_reloc_count();
Sized_relobj<size, big_endian>* relobj = reloc.get_relobj();
@@ -1500,32 +1559,36 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
void
add_global(Symbol* gsym, unsigned int type, Output_data* od, Address address)
- { this->add(od, Output_reloc_type(gsym, type, od, address, false, false)); }
+ { this->add(od, Output_reloc_type(gsym, type, od, address, false, false, false)); }
void
add_global(Symbol* gsym, unsigned int type, Output_data* od,
Sized_relobj<size, big_endian>* relobj,
unsigned int shndx, Address address)
{ this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
- false, false)); }
-
- // These are to simplify the Copy_relocs class.
+ false, false, false)); }
void
- add_global(Symbol* gsym, unsigned int type, Output_data* od, Address address,
- Address addend)
+ add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
+ uint64_t address, uint64_t addend)
{
gold_assert(addend == 0);
- this->add_global(gsym, type, od, address);
+ this->add(od, Output_reloc_type(gsym, type, od,
+ convert_types<Address, uint64_t>(address),
+ false, false, false));
}
void
- add_global(Symbol* gsym, unsigned int type, Output_data* od,
- Sized_relobj<size, big_endian>* relobj,
- unsigned int shndx, Address address, Address addend)
+ add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
+ Relobj* relobj, unsigned int shndx, uint64_t address,
+ uint64_t addend)
{
gold_assert(addend == 0);
- this->add_global(gsym, type, od, relobj, shndx, address);
+ Sized_relobj<size, big_endian>* sized_relobj =
+ static_cast<Sized_relobj<size, big_endian>*>(relobj);
+ this->add(od, Output_reloc_type(gsym, type, sized_relobj, shndx,
+ convert_types<Address, uint64_t>(address),
+ false, false, false));
}
// Add a RELATIVE reloc against a global symbol. The final relocation
@@ -1534,7 +1597,8 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
void
add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
Address address)
- { this->add(od, Output_reloc_type(gsym, type, od, address, true, true)); }
+ { this->add(od, Output_reloc_type(gsym, type, od, address, true, true,
+ false)); }
void
add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
@@ -1542,7 +1606,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
unsigned int shndx, Address address)
{
this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
- true, true));
+ true, true, false));
}
// Add a global relocation which does not use a symbol for the relocation,
@@ -1551,7 +1615,8 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
void
add_symbolless_global_addend(Symbol* gsym, unsigned int type,
Output_data* od, Address address)
- { this->add(od, Output_reloc_type(gsym, type, od, address, false, true)); }
+ { this->add(od, Output_reloc_type(gsym, type, od, address, false, true,
+ false)); }
void
add_symbolless_global_addend(Symbol* gsym, unsigned int type,
@@ -1560,7 +1625,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
unsigned int shndx, Address address)
{
this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
- false, true));
+ false, true, false));
}
// Add a reloc against a local symbol.
@@ -1571,7 +1636,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
Output_data* od, Address address)
{
this->add(od, Output_reloc_type(relobj, local_sym_index, type, od,
- address, false, false, false));
+ address, false, false, false, false));
}
void
@@ -1580,7 +1645,33 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
Output_data* od, unsigned int shndx, Address address)
{
this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
- address, false, false, false));
+ address, false, false, false, false));
+ }
+
+ void
+ add_local_generic(Relobj* relobj, unsigned int local_sym_index,
+ unsigned int type, Output_data* od, uint64_t address,
+ uint64_t addend)
+ {
+ gold_assert(addend == 0);
+ Sized_relobj<size, big_endian>* sized_relobj =
+ static_cast<Sized_relobj<size, big_endian> *>(relobj);
+ this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, od,
+ convert_types<Address, uint64_t>(address),
+ false, false, false, false));
+ }
+
+ void
+ add_local_generic(Relobj* relobj, unsigned int local_sym_index,
+ unsigned int type, Output_data* od, unsigned int shndx,
+ uint64_t address, uint64_t addend)
+ {
+ gold_assert(addend == 0);
+ Sized_relobj<size, big_endian>* sized_relobj =
+ static_cast<Sized_relobj<size, big_endian>*>(relobj);
+ this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, shndx,
+ convert_types<Address, uint64_t>(address),
+ false, false, false, false));
}
// Add a RELATIVE reloc against a local symbol.
@@ -1591,7 +1682,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
Output_data* od, Address address)
{
this->add(od, Output_reloc_type(relobj, local_sym_index, type, od,
- address, true, true, false));
+ address, true, true, false, false));
}
void
@@ -1600,7 +1691,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
Output_data* od, unsigned int shndx, Address address)
{
this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
- address, true, true, false));
+ address, true, true, false, false));
}
// Add a local relocation which does not use a symbol for the relocation,
@@ -1612,7 +1703,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
Output_data* od, Address address)
{
this->add(od, Output_reloc_type(relobj, local_sym_index, type, od,
- address, false, true, false));
+ address, false, true, false, false));
}
void
@@ -1622,7 +1713,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
Address address)
{
this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
- address, false, true, false));
+ address, false, true, false, false));
}
// Add a reloc against a local section symbol. This will be
@@ -1635,7 +1726,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
Output_data* od, Address address)
{
this->add(od, Output_reloc_type(relobj, input_shndx, type, od,
- address, false, false, true));
+ address, false, false, true, false));
}
void
@@ -1644,7 +1735,7 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
Output_data* od, unsigned int shndx, Address address)
{
this->add(od, Output_reloc_type(relobj, input_shndx, type, shndx,
- address, false, false, true));
+ address, false, false, true, false));
}
// A reloc against the STT_SECTION symbol of an output section.
@@ -1662,6 +1753,29 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
unsigned int shndx, Address address)
{ this->add(od, Output_reloc_type(os, type, relobj, shndx, address)); }
+ void
+ add_output_section_generic(Output_section* os, unsigned int type,
+ Output_data* od, uint64_t address,
+ uint64_t addend)
+ {
+ gold_assert(addend == 0);
+ this->add(od, Output_reloc_type(os, type, od,
+ convert_types<Address, uint64_t>(address)));
+ }
+
+ void
+ add_output_section_generic(Output_section* os, unsigned int type,
+ Output_data* od, Relobj* relobj,
+ unsigned int shndx, uint64_t address,
+ uint64_t addend)
+ {
+ gold_assert(addend == 0);
+ Sized_relobj<size, big_endian>* sized_relobj =
+ static_cast<Sized_relobj<size, big_endian>*>(relobj);
+ this->add(od, Output_reloc_type(os, type, sized_relobj, shndx,
+ convert_types<Address, uint64_t>(address)));
+ }
+
// Add an absolute relocation.
void
@@ -1714,7 +1828,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
add_global(Symbol* gsym, unsigned int type, Output_data* od,
Address address, Addend addend)
{ this->add(od, Output_reloc_type(gsym, type, od, address, addend,
- false, false)); }
+ false, false, false)); }
void
add_global(Symbol* gsym, unsigned int type, Output_data* od,
@@ -1722,7 +1836,30 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
unsigned int shndx, Address address,
Addend addend)
{ this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
- addend, false, false)); }
+ addend, false, false, false)); }
+
+ void
+ add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
+ uint64_t address, uint64_t addend)
+ {
+ this->add(od, Output_reloc_type(gsym, type, od,
+ convert_types<Address, uint64_t>(address),
+ convert_types<Addend, uint64_t>(addend),
+ false, false, false));
+ }
+
+ void
+ add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
+ Relobj* relobj, unsigned int shndx, uint64_t address,
+ uint64_t addend)
+ {
+ Sized_relobj<size, big_endian>* sized_relobj =
+ static_cast<Sized_relobj<size, big_endian>*>(relobj);
+ this->add(od, Output_reloc_type(gsym, type, sized_relobj, shndx,
+ convert_types<Address, uint64_t>(address),
+ convert_types<Addend, uint64_t>(addend),
+ false, false, false));
+ }
// Add a RELATIVE reloc against a global symbol. The final output
// relocation will not reference the symbol, but we must keep the symbol
@@ -1731,16 +1868,17 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
void
add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
- Address address, Addend addend)
+ Address address, Addend addend, bool use_plt_offset)
{ this->add(od, Output_reloc_type(gsym, type, od, address, addend, true,
- true)); }
+ true, use_plt_offset)); }
void
add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
Sized_relobj<size, big_endian>* relobj,
- unsigned int shndx, Address address, Addend addend)
+ unsigned int shndx, Address address, Addend addend,
+ bool use_plt_offset)
{ this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
- addend, true, true)); }
+ addend, true, true, use_plt_offset)); }
// Add a global relocation which does not use a symbol for the relocation,
// but which gets its addend from a symbol.
@@ -1749,7 +1887,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
add_symbolless_global_addend(Symbol* gsym, unsigned int type, Output_data* od,
Address address, Addend addend)
{ this->add(od, Output_reloc_type(gsym, type, od, address, addend,
- false, true)); }
+ false, true, false)); }
void
add_symbolless_global_addend(Symbol* gsym, unsigned int type,
@@ -1757,7 +1895,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
Sized_relobj<size, big_endian>* relobj,
unsigned int shndx, Address address, Addend addend)
{ this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
- addend, false, true)); }
+ addend, false, true, false)); }
// Add a reloc against a local symbol.
@@ -1767,7 +1905,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
Output_data* od, Address address, Addend addend)
{
this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, address,
- addend, false, false, false));
+ addend, false, false, false, false));
}
void
@@ -1777,7 +1915,34 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
Addend addend)
{
this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
- address, addend, false, false, false));
+ address, addend, false, false, false,
+ false));
+ }
+
+ void
+ add_local_generic(Relobj* relobj, unsigned int local_sym_index,
+ unsigned int type, Output_data* od, uint64_t address,
+ uint64_t addend)
+ {
+ Sized_relobj<size, big_endian>* sized_relobj =
+ static_cast<Sized_relobj<size, big_endian> *>(relobj);
+ this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, od,
+ convert_types<Address, uint64_t>(address),
+ convert_types<Addend, uint64_t>(addend),
+ false, false, false, false));
+ }
+
+ void
+ add_local_generic(Relobj* relobj, unsigned int local_sym_index,
+ unsigned int type, Output_data* od, unsigned int shndx,
+ uint64_t address, uint64_t addend)
+ {
+ Sized_relobj<size, big_endian>* sized_relobj =
+ static_cast<Sized_relobj<size, big_endian>*>(relobj);
+ this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, shndx,
+ convert_types<Address, uint64_t>(address),
+ convert_types<Addend, uint64_t>(addend),
+ false, false, false, false));
}
// Add a RELATIVE reloc against a local symbol.
@@ -1785,20 +1950,23 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
void
add_local_relative(Sized_relobj<size, big_endian>* relobj,
unsigned int local_sym_index, unsigned int type,
- Output_data* od, Address address, Addend addend)
+ Output_data* od, Address address, Addend addend,
+ bool use_plt_offset)
{
this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, address,
- addend, true, true, false));
+ addend, true, true, false,
+ use_plt_offset));
}
void
add_local_relative(Sized_relobj<size, big_endian>* relobj,
unsigned int local_sym_index, unsigned int type,
Output_data* od, unsigned int shndx, Address address,
- Addend addend)
+ Addend addend, bool use_plt_offset)
{
this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
- address, addend, true, true, false));
+ address, addend, true, true, false,
+ use_plt_offset));
}
// Add a local relocation which does not use a symbol for the relocation,
@@ -1810,7 +1978,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
Output_data* od, Address address, Addend addend)
{
this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, address,
- addend, false, true, false));
+ addend, false, true, false, false));
}
void
@@ -1820,7 +1988,8 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
Address address, Addend addend)
{
this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
- address, addend, false, true, false));
+ address, addend, false, true, false,
+ false));
}
// Add a reloc against a local section symbol. This will be
@@ -1833,7 +2002,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
Output_data* od, Address address, Addend addend)
{
this->add(od, Output_reloc_type(relobj, input_shndx, type, od, address,
- addend, false, false, true));
+ addend, false, false, true, false));
}
void
@@ -1843,7 +2012,8 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
Addend addend)
{
this->add(od, Output_reloc_type(relobj, input_shndx, type, shndx,
- address, addend, false, false, true));
+ address, addend, false, false, true,
+ false));
}
// A reloc against the STT_SECTION symbol of an output section.
@@ -1860,6 +2030,29 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
{ this->add(od, Output_reloc_type(os, type, relobj, shndx, address,
addend)); }
+ void
+ add_output_section_generic(Output_section* os, unsigned int type,
+ Output_data* od, uint64_t address,
+ uint64_t addend)
+ {
+ this->add(od, Output_reloc_type(os, type, od,
+ convert_types<Address, uint64_t>(address),
+ convert_types<Addend, uint64_t>(addend)));
+ }
+
+ void
+ add_output_section_generic(Output_section* os, unsigned int type,
+ Output_data* od, Relobj* relobj,
+ unsigned int shndx, uint64_t address,
+ uint64_t addend)
+ {
+ Sized_relobj<size, big_endian>* sized_relobj =
+ static_cast<Sized_relobj<size, big_endian>*>(relobj);
+ this->add(od, Output_reloc_type(os, type, sized_relobj, shndx,
+ convert_types<Address, uint64_t>(address),
+ convert_types<Addend, uint64_t>(addend)));
+ }
+
// Add an absolute relocation.
void
@@ -1959,29 +2152,50 @@ class Output_data_group : public Output_section_data
// Output_data_got is used to manage a GOT. Each entry in the GOT is
// for one symbol--either a global symbol or a local symbol in an
// object. The target specific code adds entries to the GOT as
-// needed.
+// needed. The GOT_SIZE template parameter is the size in bits of a
+// GOT entry, typically 32 or 64.
-template<int size, bool big_endian>
-class Output_data_got : public Output_section_data_build
+class Output_data_got_base : public Output_section_data_build
+{
+ public:
+ Output_data_got_base(uint64_t align)
+ : Output_section_data_build(align)
+ { }
+
+ Output_data_got_base(off_t data_size, uint64_t align)
+ : Output_section_data_build(data_size, align)
+ { }
+
+ // Reserve the slot at index I in the GOT.
+ void
+ reserve_slot(unsigned int i)
+ { this->do_reserve_slot(i); }
+
+ protected:
+ // Reserve the slot at index I in the GOT.
+ virtual void
+ do_reserve_slot(unsigned int i) = 0;
+};
+
+template<int got_size, bool big_endian>
+class Output_data_got : public Output_data_got_base
{
public:
- typedef typename elfcpp::Elf_types<size>::Elf_Addr Valtype;
- typedef Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian> Rel_dyn;
- typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian> Rela_dyn;
+ typedef typename elfcpp::Elf_types<got_size>::Elf_Addr Valtype;
Output_data_got()
- : Output_section_data_build(Output_data::default_alignment_for_size(size)),
+ : Output_data_got_base(Output_data::default_alignment_for_size(got_size)),
entries_(), free_list_()
{ }
Output_data_got(off_t data_size)
- : Output_section_data_build(data_size,
- Output_data::default_alignment_for_size(size)),
+ : Output_data_got_base(data_size,
+ Output_data::default_alignment_for_size(got_size)),
entries_(), free_list_()
{
// For an incremental update, we have an existing GOT section.
// Initialize the list of entries and the free list.
- this->entries_.resize(data_size / (size / 8));
+ this->entries_.resize(data_size / (got_size / 8));
this->free_list_.init(data_size, false);
}
@@ -1999,62 +2213,39 @@ class Output_data_got : public Output_section_data_build
// relocation of type R_TYPE for the GOT entry.
void
add_global_with_rel(Symbol* gsym, unsigned int got_type,
- Rel_dyn* rel_dyn, unsigned int r_type);
-
- void
- add_global_with_rela(Symbol* gsym, unsigned int got_type,
- Rela_dyn* rela_dyn, unsigned int r_type);
+ Output_data_reloc_generic* rel_dyn, unsigned int r_type);
// Add a pair of entries for a global symbol to the GOT, and add
// dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively.
void
add_global_pair_with_rel(Symbol* gsym, unsigned int got_type,
- Rel_dyn* rel_dyn, unsigned int r_type_1,
- unsigned int r_type_2);
-
- void
- add_global_pair_with_rela(Symbol* gsym, unsigned int got_type,
- Rela_dyn* rela_dyn, unsigned int r_type_1,
- unsigned int r_type_2);
+ Output_data_reloc_generic* rel_dyn,
+ unsigned int r_type_1, unsigned int r_type_2);
// Add an entry for a local symbol to the GOT. This returns true if
// this is a new GOT entry, false if the symbol already has a GOT
// entry.
bool
- add_local(Sized_relobj_file<size, big_endian>* object, unsigned int sym_index,
- unsigned int got_type);
+ add_local(Relobj* object, unsigned int sym_index, unsigned int got_type);
// Like add_local, but use the PLT offset of the local symbol if it
// has one.
bool
- add_local_plt(Sized_relobj_file<size, big_endian>* object,
- unsigned int sym_index,
- unsigned int got_type);
+ add_local_plt(Relobj* object, unsigned int sym_index, unsigned int got_type);
// Add an entry for a local symbol to the GOT, and add a dynamic
// relocation of type R_TYPE for the GOT entry.
void
- add_local_with_rel(Sized_relobj_file<size, big_endian>* object,
- unsigned int sym_index, unsigned int got_type,
- Rel_dyn* rel_dyn, unsigned int r_type);
-
- void
- add_local_with_rela(Sized_relobj_file<size, big_endian>* object,
- unsigned int sym_index, unsigned int got_type,
- Rela_dyn* rela_dyn, unsigned int r_type);
+ add_local_with_rel(Relobj* object, unsigned int sym_index,
+ unsigned int got_type, Output_data_reloc_generic* rel_dyn,
+ unsigned int r_type);
// Add a pair of entries for a local symbol to the GOT, and add
// dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively.
void
- add_local_pair_with_rel(Sized_relobj_file<size, big_endian>* object,
- unsigned int sym_index, unsigned int shndx,
- unsigned int got_type, Rel_dyn* rel_dyn,
- unsigned int r_type_1, unsigned int r_type_2);
-
- void
- add_local_pair_with_rela(Sized_relobj_file<size, big_endian>* object,
- unsigned int sym_index, unsigned int shndx,
- unsigned int got_type, Rela_dyn* rela_dyn,
+ add_local_pair_with_rel(Relobj* object, unsigned int sym_index,
+ unsigned int shndx, unsigned int got_type,
+ Output_data_reloc_generic* rel_dyn,
unsigned int r_type_1, unsigned int r_type_2);
// Add a constant to the GOT. This returns the offset of the new
@@ -2066,15 +2257,10 @@ class Output_data_got : public Output_section_data_build
return got_offset;
}
- // Reserve a slot in the GOT.
- void
- reserve_slot(unsigned int i)
- { this->free_list_.remove(i * size / 8, (i + 1) * size / 8); }
-
// Reserve a slot in the GOT for a local symbol.
void
- reserve_local(unsigned int i, Sized_relobj<size, big_endian>* object,
- unsigned int sym_index, unsigned int got_type);
+ reserve_local(unsigned int i, Relobj* object, unsigned int sym_index,
+ unsigned int got_type);
// Reserve a slot in the GOT for a global symbol.
void
@@ -2090,6 +2276,11 @@ class Output_data_got : public Output_section_data_build
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** GOT")); }
+ // Reserve the slot at index I in the GOT.
+ virtual void
+ do_reserve_slot(unsigned int i)
+ { this->free_list_.remove(i * got_size / 8, (i + 1) * got_size / 8); }
+
private:
// This POD class holds a single GOT entry.
class Got_entry
@@ -2106,8 +2297,8 @@ class Output_data_got : public Output_section_data_build
{ this->u_.gsym = gsym; }
// Create a local symbol entry.
- Got_entry(Sized_relobj_file<size, big_endian>* object,
- unsigned int local_sym_index, bool use_plt_offset)
+ Got_entry(Relobj* object, unsigned int local_sym_index,
+ bool use_plt_offset)
: local_sym_index_(local_sym_index), use_plt_offset_(use_plt_offset)
{
gold_assert(local_sym_index != GSYM_CODE
@@ -2138,7 +2329,7 @@ class Output_data_got : public Output_section_data_build
union
{
// For a local symbol, the object.
- Sized_relobj_file<size, big_endian>* object;
+ Relobj* object;
// For a global symbol, the symbol.
Symbol* gsym;
// For a constant, the constant.
@@ -2164,7 +2355,7 @@ class Output_data_got : public Output_section_data_build
// Return the offset into the GOT of GOT entry I.
unsigned int
got_offset(unsigned int i) const
- { return i * (size / 8); }
+ { return i * (got_size / 8); }
// Return the offset into the GOT of the last entry added.
unsigned int
@@ -2628,6 +2819,10 @@ class Output_fill
: is_big_endian_(parameters->target().is_big_endian())
{ }
+ virtual
+ ~Output_fill()
+ { }
+
// Return the smallest size chunk of free space that can be
// filled with a dummy compilation unit.
size_t
@@ -2761,7 +2956,7 @@ class Output_section : public Output_data
typedef std::map<Section_id, unsigned int> Section_layout_order;
void
- update_section_layout(const Section_layout_order& order_map);
+ update_section_layout(const Section_layout_order* order_map);
// Update the output section flags based on input section flags.
void
diff --git a/binutils-2.22/gold/parameters.cc b/binutils-2.22/gold/parameters.cc
index c14bd1e..d69b62c 100644
--- a/binutils-2.22/gold/parameters.cc
+++ b/binutils-2.22/gold/parameters.cc
@@ -1,6 +1,7 @@
// parameters.cc -- general parameters for a link using gold
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -64,7 +65,7 @@ Set_parameters_target_once set_parameters_target_once(&static_parameters);
// Class Parameters.
Parameters::Parameters()
- : errors_(NULL), options_(NULL), target_(NULL),
+ : errors_(NULL), timer_(NULL), options_(NULL), target_(NULL),
doing_static_link_valid_(false), doing_static_link_(false),
debug_(0), incremental_mode_(General_options::INCREMENTAL_OFF),
set_parameters_target_once_(&set_parameters_target_once)
@@ -79,6 +80,13 @@ Parameters::set_errors(Errors* errors)
}
void
+Parameters::set_timer(Timer* timer)
+{
+ gold_assert(this->timer_ == NULL);
+ this->timer_ = timer;
+}
+
+void
Parameters::set_options(const General_options* options)
{
gold_assert(!this->options_valid());
@@ -205,7 +213,7 @@ Parameters::check_target_endianness()
gold_assert(endianness == General_options::ENDIANNESS_LITTLE);
big_endian = false;;
}
-
+
if (this->target().is_big_endian() != big_endian)
gold_error(_("input file does not match -EB/EL option"));
}
@@ -270,6 +278,10 @@ set_parameters_errors(Errors* errors)
{ static_parameters.set_errors(errors); }
void
+set_parameters_timer(Timer* timer)
+{ static_parameters.set_timer(timer); }
+
+void
set_parameters_options(const General_options* options)
{ static_parameters.set_options(options); }
@@ -341,7 +353,8 @@ parameters_force_valid_target()
else
is_big_endian = GOLD_DEFAULT_BIG_ENDIAN;
- Target* target = select_target(elfcpp::GOLD_DEFAULT_MACHINE,
+ Target* target = select_target(NULL, 0,
+ elfcpp::GOLD_DEFAULT_MACHINE,
GOLD_DEFAULT_SIZE,
is_big_endian,
elfcpp::GOLD_DEFAULT_OSABI,
diff --git a/binutils-2.22/gold/parameters.h b/binutils-2.22/gold/parameters.h
index 09b0516..10de2ae 100644
--- a/binutils-2.22/gold/parameters.h
+++ b/binutils-2.22/gold/parameters.h
@@ -28,6 +28,7 @@ namespace gold
class General_options;
class Errors;
+class Timer;
class Target;
template<int size, bool big_endian>
class Sized_target;
@@ -57,6 +58,9 @@ class Parameters
set_errors(Errors* errors);
void
+ set_timer(Timer* timer);
+
+ void
set_options(const General_options* options);
void
@@ -70,6 +74,11 @@ class Parameters
errors() const
{ return this->errors_; }
+ // Return the timer object.
+ Timer*
+ timer() const
+ { return this->timer_; }
+
// Whether the options are valid. This should not normally be
// called, but it is needed by gold_exit.
bool
@@ -177,6 +186,7 @@ class Parameters
friend class Set_parameters_target_once;
Errors* errors_;
+ Timer* timer_;
const General_options* options_;
Target* target_;
bool doing_static_link_valid_;
@@ -196,6 +206,9 @@ extern void
set_parameters_errors(Errors* errors);
extern void
+set_parameters_timer(Timer* timer);
+
+extern void
set_parameters_options(const General_options* options);
extern void
diff --git a/binutils-2.22/gold/plugin.cc b/binutils-2.22/gold/plugin.cc
index 3ccd8d0..5aadc55 100644
--- a/binutils-2.22/gold/plugin.cc
+++ b/binutils-2.22/gold/plugin.cc
@@ -184,6 +184,8 @@ Plugin::load()
tv[i].tv_u.tv_val = LDPO_REL;
else if (parameters->options().shared())
tv[i].tv_u.tv_val = LDPO_DYN;
+ else if (parameters->options().pie())
+ tv[i].tv_u.tv_val = LDPO_PIE;
else
tv[i].tv_u.tv_val = LDPO_EXEC;
@@ -818,7 +820,9 @@ Pluginobj::Pluginobj(const std::string& name, Input_file* input_file,
}
// Return TRUE if a defined symbol is referenced from outside the
-// universe of claimed objects.
+// universe of claimed objects. Only references from relocatable,
+// non-IR (unclaimed) objects count as a reference. References from
+// dynamic objects count only as "visible".
static inline bool
is_referenced_from_outside(Symbol* lsym)
@@ -838,6 +842,8 @@ is_referenced_from_outside(Symbol* lsym)
static inline bool
is_visible_from_outside(Symbol* lsym)
{
+ if (lsym->in_dyn())
+ return true;
if (parameters->options().export_dynamic() || parameters->options().shared())
return lsym->is_externally_visible();
return false;
@@ -1155,13 +1161,14 @@ Sized_pluginobj<size, big_endian>::do_section_name(unsigned int)
// Return a view of the contents of a section. Not used for plugin objects.
template<int size, bool big_endian>
-Object::Location
-Sized_pluginobj<size, big_endian>::do_section_contents(unsigned int)
+const unsigned char*
+Sized_pluginobj<size, big_endian>::do_section_contents(
+ unsigned int,
+ section_size_type*,
+ bool)
{
- Location loc(0, 0);
-
gold_unreachable();
- return loc;
+ return NULL;
}
// Return section flags. Not used for plugin objects.
@@ -1244,14 +1251,18 @@ Sized_pluginobj<size, big_endian>::do_initialize_xindex()
return NULL;
}
-// Get symbol counts. Not used for plugin objects.
+// Get symbol counts. Don't count plugin objects; the replacement
+// files will provide the counts.
template<int size, bool big_endian>
void
-Sized_pluginobj<size, big_endian>::do_get_global_symbol_counts(const Symbol_table*,
- size_t*, size_t*) const
+Sized_pluginobj<size, big_endian>::do_get_global_symbol_counts(
+ const Symbol_table*,
+ size_t* defined,
+ size_t* used) const
{
- gold_unreachable();
+ *defined = 0;
+ *used = 0;
}
// Get symbols. Not used for plugin objects.
@@ -1630,7 +1641,7 @@ get_input_section_contents(const struct ld_plugin_section section,
// which they should appear in the final layout.
static enum ld_plugin_status
-update_section_order(const struct ld_plugin_section *section_list,
+update_section_order(const struct ld_plugin_section* section_list,
unsigned int num_sections)
{
gold_assert(parameters->options().has_plugins());
@@ -1641,8 +1652,14 @@ update_section_order(const struct ld_plugin_section *section_list,
if (section_list == NULL)
return LDPS_ERR;
- std::map<Section_id, unsigned int> order_map;
+ Layout* layout = parameters->options().plugins()->layout();
+ gold_assert (layout != NULL);
+ std::map<Section_id, unsigned int>* order_map
+ = layout->get_section_order_map();
+
+ /* Store the mapping from Section_id to section position in layout's
+ order_map to consult after output sections are added. */
for (unsigned int i = 0; i < num_sections; ++i)
{
Object* obj = parameters->options().plugins()->get_elf_object(
@@ -1651,17 +1668,9 @@ update_section_order(const struct ld_plugin_section *section_list,
return LDPS_BAD_HANDLE;
unsigned int shndx = section_list[i].shndx;
Section_id secn_id(obj, shndx);
- order_map[secn_id] = i + 1;
+ (*order_map)[secn_id] = i + 1;
}
- Layout* layout = parameters->options().plugins()->layout();
- gold_assert (layout != NULL);
-
- for (Layout::Section_list::const_iterator p = layout->section_list().begin();
- p != layout->section_list().end();
- ++p)
- (*p)->update_section_layout(order_map);
-
return LDPS_OK;
}
diff --git a/binutils-2.22/gold/plugin.h b/binutils-2.22/gold/plugin.h
index 32ffe35..1891d6b 100644
--- a/binutils-2.22/gold/plugin.h
+++ b/binutils-2.22/gold/plugin.h
@@ -493,8 +493,9 @@ class Sized_pluginobj : public Pluginobj
do_section_name(unsigned int shndx);
// Return a view of the contents of a section.
- Object::Location
- do_section_contents(unsigned int shndx);
+ const unsigned char*
+ do_section_contents(unsigned int shndx, section_size_type* plen,
+ bool cache);
// Return section flags.
uint64_t
diff --git a/binutils-2.22/gold/po/es.gmo b/binutils-2.22/gold/po/es.gmo
index e79c304..27b0753 100644
--- a/binutils-2.22/gold/po/es.gmo
+++ b/binutils-2.22/gold/po/es.gmo
Binary files differ
diff --git a/binutils-2.22/gold/po/es.po b/binutils-2.22/gold/po/es.po
index 6825c3e..d203329 100644
--- a/binutils-2.22/gold/po/es.po
+++ b/binutils-2.22/gold/po/es.po
@@ -1,14 +1,14 @@
-# Mensajes en español para gold 2.20.90.
+# Mensajes en español para gold 2.21.53.
# Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
# This file is distributed under the same license as the binutils package.
# Cristian Othón Martínez Vera <cfuga@cfuga.mx>, 2008, 2009, 2010, 2011.
#
msgid ""
msgstr ""
-"Project-Id-Version: gold 2.20.90\n"
+"Project-Id-Version: gold 2.21.53\n"
"Report-Msgid-Bugs-To: bug-binutils@gnu.org\n"
"POT-Creation-Date: 2010-03-03 15:08+0100\n"
-"PO-Revision-Date: 2011-08-24 11:49-0500\n"
+"PO-Revision-Date: 2011-09-25 20:48-0500\n"
"Last-Translator: Cristian Othón Martínez Vera <cfuga@cfuga.mx>\n"
"Language-Team: Spanish <es@li.org>\n"
"Language: es\n"
diff --git a/binutils-2.22/gold/po/fi.gmo b/binutils-2.22/gold/po/fi.gmo
index 59175d3..8e5149d 100644
--- a/binutils-2.22/gold/po/fi.gmo
+++ b/binutils-2.22/gold/po/fi.gmo
Binary files differ
diff --git a/binutils-2.22/gold/po/fi.po b/binutils-2.22/gold/po/fi.po
index 0f2cfed..59f28eb 100644
--- a/binutils-2.22/gold/po/fi.po
+++ b/binutils-2.22/gold/po/fi.po
@@ -1,81 +1,171 @@
# Finnish messages for gold.
-# Copyright © 2010 Free Software Foundation, Inc.
+# Copyright © 2010, 2011 Free Software Foundation, Inc.
# This file is distributed under the same license as the binutils package.
-# Jorma Karvonen <karvonen.jorma@gmail.com>, 2010.
+# Jorma Karvonen <karvonen.jorma@gmail.com>, 2010-2011.
#
msgid ""
msgstr ""
-"Project-Id-Version: gold 2.20\n"
-"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-09-09 17:16+0930\n"
-"PO-Revision-Date: 2010-03-02 17:04+0200\n"
+"Project-Id-Version: gold 2.21.53\n"
+"Report-Msgid-Bugs-To: bug-binutils@gnu.org\n"
+"POT-Creation-Date: 2010-03-03 15:08+0100\n"
+"PO-Revision-Date: 2011-09-23 13:25+0200\n"
"Last-Translator: Jorma Karvonen <karvonen.jorma@gmail.com>\n"
"Language-Team: Finnish <translation-team-fi@lists.sourceforge.net>\n"
+"Language: fi\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-#: archive.cc:107
+#: archive.cc:119
#, c-format
msgid "%s: no archive symbol table (run ranlib)"
msgstr "%s: ei arkistosymbolitaulua (suorita ranlib)"
-#: archive.cc:189
+#: archive.cc:204
#, c-format
msgid "%s: bad archive symbol table names"
msgstr "%s: virheelliset arkistosymbolitaulunimet"
-#: archive.cc:221
+#: archive.cc:236
#, c-format
msgid "%s: malformed archive header at %zu"
msgstr "%s: vääränmuotoinen arkisto-otsake siirrososoitteessa %zu"
-#: archive.cc:241
+#: archive.cc:256
#, c-format
msgid "%s: malformed archive header size at %zu"
msgstr "%s: vääränmuotoinen arkisto-otsakekoko siirrososoitteessa %zu"
-#: archive.cc:252
+#: archive.cc:267
#, c-format
msgid "%s: malformed archive header name at %zu"
msgstr "%s: vääränmuotoinen arkisto-otsakenimi siirrososoitteessa %zu"
-#: archive.cc:282
+#: archive.cc:297
#, c-format
msgid "%s: bad extended name index at %zu"
msgstr "%s: väärä laajennettu nimi-indeksi siirrososoitteessa %zu"
-#: archive.cc:292
+#: archive.cc:307
#, c-format
msgid "%s: bad extended name entry at header %zu"
msgstr "%s: väärä laajennettu nimimerkintä otsakeosoitteessa %zu"
-#: archive.cc:389
+#: archive.cc:404
#, c-format
msgid "%s: short archive header at %zu"
msgstr "%s: lyhyt arkisto-otsake siirrososoitteessa %zu"
-#: archive.cc:530 archive.cc:545
+#: archive.cc:560
#, c-format
msgid "%s: member at %zu is not an ELF object"
msgstr "%s: jäsen siirrososoitteessa %zu ei ole ELF-objekti"
-#: archive.cc:775
+#: archive.cc:879
#, c-format
msgid "%s: archive libraries: %u\n"
msgstr "%s: arkistokirjastot: %u\n"
-#: archive.cc:777
+#: archive.cc:881
#, c-format
msgid "%s: total archive members: %u\n"
msgstr "%s: yhteensä arkistojäseniä: %u\n"
-#: archive.cc:779
+#: archive.cc:883
#, c-format
msgid "%s: loaded archive members: %u\n"
msgstr "%s: ladattuja arkistojäseniä: %u\n"
+#: arm.cc:1149 i386.cc:536 sparc.cc:1087 x86_64.cc:565
+msgid "** PLT"
+msgstr "** PLT"
+
+# Report an unsupported relocation against a local symbol.
+#: arm.cc:1364 i386.cc:880 powerpc.cc:1014 sparc.cc:1502 x86_64.cc:955
+#: x86_64.cc:1265
+#, c-format
+msgid "%s: unsupported reloc %u against local symbol"
+msgstr "%s: tukematon sijoitus %u paikallista symbolia kohtaan"
+
+#: arm.cc:1404 powerpc.cc:1105 sparc.cc:1592 x86_64.cc:992
+msgid "requires unsupported dynamic reloc; recompile with -fPIC"
+msgstr "vaatii tukematonta dynaamista reloc-tietuetta, käännä uudelleen valitsimella -fPIC"
+
+#. These are relocations which should only be seen by the
+#. dynamic linker, and should never be seen here.
+#: arm.cc:1519 arm.cc:1739 arm.cc:2354 i386.cc:1002 i386.cc:1334
+#: powerpc.cc:1223 powerpc.cc:1432 sparc.cc:1877 sparc.cc:2238 x86_64.cc:1145
+#: x86_64.cc:1453
+#, c-format
+msgid "%s: unexpected reloc %u in object file"
+msgstr "%s: odottamaton sijoitus %u objektitiedostossa"
+
+# Report an unsupported relocation against a global symbol.
+#: arm.cc:1538 i386.cc:1171 powerpc.cc:1242 sparc.cc:1896 x86_64.cc:1279
+#: x86_64.cc:1571
+#, c-format
+msgid "%s: unsupported reloc %u against global symbol %s"
+msgstr "%s: tukematon sijoitus %u yleissymbolia %s kohtaan"
+
+# Scan relocations for a section.
+#: arm.cc:1804 i386.cc:1542
+#, c-format
+msgid "%s: unsupported RELA reloc section"
+msgstr "%s: tukematon RELA-sijoituslohko"
+
+#: arm.cc:2047
+msgid "relocation R_ARM_MOVW_ABS_NC cannot be used when makinga shared object; recompile with -fPIC"
+msgstr "sijoitusta R_ARM_MOVW_ABS_NC ei voi käyttää kun tehdään jaettua objektia: käännä uudelleen valitsimella -fPIC"
+
+#: arm.cc:2056
+msgid "relocation R_ARM_MOVT_ABS cannot be used when makinga shared object; recompile with -fPIC"
+msgstr "sijoitusta R_ARM_MOVT_ABS ei voi käyttää kun tehdään jaettua objektia: käännä uudelleen valitsimella -fPIC"
+
+#: arm.cc:2067
+msgid "relocation R_ARM_THM_MOVW_ABS_NC cannot be used whenmaking a shared object; recompile with -fPIC"
+msgstr "sijoitusta R_ARM_THM_MOVW_ABS_NC ei voi käyttää kun tehdään jaettua objektia: käännä uudelleen valitsimella -fPIC"
+
+#: arm.cc:2077
+msgid "relocation R_ARM_THM_MOVT_ABS cannot be used whenmaking a shared object; recompile with -fPIC"
+msgstr "sijoitusta R_ARM_THM_MOVT_ABS ei voi käyttää kun tehdään jaettua objektia: käännä uudelleen valitsimella -fPIC"
+
+#: arm.cc:2141
+msgid "cannot find origin of R_ARM_BASE_PREL"
+msgstr "ei voida löytää R_ARM_BASE_PREL-alkua"
+
+#: arm.cc:2169
+msgid "cannot find origin of R_ARM_BASE_ABS"
+msgstr "ei voida löytää R_ARM_BASE_ABS-alkua"
+
+#: arm.cc:2230 i386.cc:1820 i386.cc:2521 powerpc.cc:1798 sparc.cc:2711
+#: x86_64.cc:1935 x86_64.cc:2518
+#, c-format
+msgid "unexpected reloc %u in object file"
+msgstr "tukematon sijoitus %u objektitiedostossa"
+
+#: arm.cc:2236 i386.cc:1852 i386.cc:1931 i386.cc:1983 i386.cc:2014
+#: i386.cc:2076 powerpc.cc:1804 sparc.cc:2717 sparc.cc:2900 sparc.cc:2961
+#: sparc.cc:3068 x86_64.cc:1956 x86_64.cc:2039 x86_64.cc:2094 x86_64.cc:2119
+#, c-format
+msgid "unsupported reloc %u"
+msgstr "tukematon sijoitus %u"
+
+#: arm.cc:2248
+#, c-format
+msgid "relocation overflow in relocation %u"
+msgstr "sijoitusylivuoto sijoituksessa %u"
+
+#: arm.cc:2256
+#, c-format
+msgid "unexpected opcode while processing relocation %u"
+msgstr "odottamaton käskykoodi käsiteltäessä sijoitusta %u"
+
+#: arm.cc:2359 i386.cc:2535
+#, c-format
+msgid "unsupported reloc %u in object file"
+msgstr "tukematon sijoitus %u objektitiedostossa"
+
#: binary.cc:129
#, c-format
msgid "cannot open %s: %s:"
@@ -90,16 +180,16 @@ msgstr "ei tiivistetä lohkodataa: zlib-virhe"
msgid "cannot open symbol count file %s: %s"
msgstr "ei voi avata symbolilukumäärätiedostoa %s: %s"
-#: descriptors.cc:94
+#: descriptors.cc:116
#, c-format
msgid "file %s was removed during the link"
msgstr "tiedosto %s poistettiin linkityksen aikana"
-#: descriptors.cc:133
+#: descriptors.cc:169
msgid "out of file descriptors and couldn't close any"
msgstr "ei ole enää tiedostokuvaajia eikä voitu sulkea yhtään"
-#: descriptors.cc:154 descriptors.cc:189
+#: descriptors.cc:190 descriptors.cc:226
#, c-format
msgid "while closing %s: %s"
msgstr "suljetaessa tiedostokuvaajaa %s: %s"
@@ -113,115 +203,115 @@ msgstr "%s: ei voi lukea hakemistoa: %s"
msgid "Unusually large LEB128 decoded, debug information may be corrupted"
msgstr "Epätavallisen iso LEB128 dekoodattu, vianjäljitystiedot saattavat olla vääristyneitä"
-#: dynobj.cc:169
+#: dynobj.cc:164
#, c-format
msgid "unexpected duplicate type %u section: %u, %u"
msgstr "odottamaton kaksoiskappaletyyppi %u lohko: %u, %u"
-#: dynobj.cc:205
+#: dynobj.cc:200
#, c-format
msgid "unexpected link in section %u header: %u != %u"
msgstr "odottamaton linkitys lohkossa %u otsake: %u != %u"
-#: dynobj.cc:241
+#: dynobj.cc:236
#, c-format
msgid "DYNAMIC section %u link out of range: %u"
msgstr "DYNAAMINEN lohko %u linkki lukualueen ulkopuolella: %u"
-#: dynobj.cc:249
+#: dynobj.cc:244
#, c-format
msgid "DYNAMIC section %u link %u is not a strtab"
msgstr "DYNAAMINEN lohko %u linkki %u ei ole ”strtab”"
-#: dynobj.cc:278
+#: dynobj.cc:273
#, c-format
msgid "DT_SONAME value out of range: %lld >= %lld"
msgstr "DT_SONAME-arvo lukualueen ulkopuolella: %lld >= %lld"
-#: dynobj.cc:290
+#: dynobj.cc:285
#, c-format
msgid "DT_NEEDED value out of range: %lld >= %lld"
msgstr "DT_NEEDED-arvo lukualueen ulkopuolella: %lld >= %lld"
-#: dynobj.cc:303
+#: dynobj.cc:298
msgid "missing DT_NULL in dynamic segment"
msgstr "puuttuva DT_NULL dynaamisessa segmentissä"
-#: dynobj.cc:349
+#: dynobj.cc:344
#, c-format
msgid "invalid dynamic symbol table name index: %u"
msgstr "virheellinen dynaaminen symbolitaulunimi-indeksi: %u"
-#: dynobj.cc:356
+#: dynobj.cc:351
#, c-format
msgid "dynamic symbol table name section has wrong type: %u"
msgstr "dynaamisella symbolitaulunimilohkolla on väärä tyyppi: %u"
-#: dynobj.cc:443 object.cc:376 object.cc:884
+#: dynobj.cc:438 object.cc:463 object.cc:1106
#, c-format
msgid "bad section name offset for section %u: %lu"
msgstr "väärä lohkonimisiirrososoite lohkolle %u: %lu"
-#: dynobj.cc:472
+#: dynobj.cc:468
#, c-format
msgid "duplicate definition for version %u"
msgstr "kaksoiskappalemäärittely versiolle %u"
-#: dynobj.cc:501
+#: dynobj.cc:497
#, c-format
msgid "unexpected verdef version %u"
msgstr "odottamaton verdef-versio %u"
-#: dynobj.cc:517
+#: dynobj.cc:513
#, c-format
msgid "verdef vd_cnt field too small: %u"
msgstr "verdef vd_cnt-kenttä liian pieni: %u"
-#: dynobj.cc:525
+#: dynobj.cc:521
#, c-format
msgid "verdef vd_aux field out of range: %u"
msgstr "verdef vd_aux-kenttä lukualueen ulkopuolella: %u"
-#: dynobj.cc:536
+#: dynobj.cc:532
#, c-format
msgid "verdaux vda_name field out of range: %u"
msgstr "verdaux vda_name -kenttä lukualueen ulkopuolella: %u"
-#: dynobj.cc:546
+#: dynobj.cc:542
#, c-format
msgid "verdef vd_next field out of range: %u"
-msgstr "verdef vd_next -kenttää lukualueen ulkopuolella: %u"
+msgstr "verdef vd_next -kenttä lukualueen ulkopuolella: %u"
-#: dynobj.cc:580
+#: dynobj.cc:576
#, c-format
msgid "unexpected verneed version %u"
msgstr "odottamaton verneed-versio %u"
-#: dynobj.cc:589
+#: dynobj.cc:585
#, c-format
msgid "verneed vn_aux field out of range: %u"
msgstr "verneed vn_aux-kenttä lukualueen ulkopuolella: %u"
-#: dynobj.cc:603
+#: dynobj.cc:599
#, c-format
msgid "vernaux vna_name field out of range: %u"
msgstr "vernaux vna_name-kenttä lukualueen ulkopuolella: %u"
-#: dynobj.cc:614
+#: dynobj.cc:610
#, c-format
msgid "verneed vna_next field out of range: %u"
msgstr "verneed vna_next-kenttä lukualueen ulkopuolella: %u"
-#: dynobj.cc:625
+#: dynobj.cc:621
#, c-format
msgid "verneed vn_next field out of range: %u"
msgstr "verneed vn_next-kenttä lukualueen ulkopuolella: %u"
-#: dynobj.cc:673
+#: dynobj.cc:670
msgid "size of dynamic symbols is not multiple of symbol size"
msgstr "dynaamisten symbolien koko ei ole symbolikoon monikerta"
-#: dynobj.cc:1425
+#: dynobj.cc:1435
#, c-format
msgid "symbol %s has undefined version %s"
msgstr "symbolilla %s on määrittelemätön versio %s"
@@ -234,27 +324,42 @@ msgstr "** eh_frame_hdr"
msgid "** eh_frame"
msgstr "** eh_frame"
-#: errors.cc:106
+#: errors.cc:81
+#, c-format
+msgid "%s: fatal error: "
+msgstr "%s: kohtalokas virhe: "
+
+#: errors.cc:92
+#, c-format
+msgid "%s: error: "
+msgstr "%s: virhe: "
+
+#: errors.cc:104
#, c-format
msgid "%s: warning: "
msgstr "%s: varoitus: "
-#: errors.cc:146
+#: errors.cc:128
+#, c-format
+msgid "%s: %s: error: "
+msgstr "%s: %s: virhe: "
+
+#: errors.cc:144
#, c-format
msgid "%s: %s: warning: "
msgstr "%s: %s: varoitus: "
-#: errors.cc:172
+#: errors.cc:167
#, c-format
-msgid "%s: %s: undefined reference to '%s'\n"
-msgstr "%s: %s: määrittelemätön viite kohteeseen ’%s’\n"
+msgid "%s: %s: error: undefined reference to '%s'\n"
+msgstr "%s: %s: virhe: määrittelemätön viite kohteeseen ’%s’\n"
-#: errors.cc:176
+#: errors.cc:172
#, c-format
-msgid "%s: %s: undefined reference to '%s', version '%s'\n"
-msgstr "%s: %s: määrittelemätön viite kohteeseen ’%s’, versio ’%s’\n"
+msgid "%s: %s: error: undefined reference to '%s', version '%s'\n"
+msgstr "%s: %s: virhe: määrittelemätön viite kohteeseen ’%s’, versio ’%s’\n"
-#: errors.cc:186
+#: errors.cc:182
#, c-format
msgid "%s: "
msgstr "%s: "
@@ -274,10 +379,6 @@ msgstr "virheellinen viite dot-symboliin SECTIONS-lauseen ulkopuolella"
msgid "unary "
msgstr "unaari "
-#: expression.cc:278 expression.cc:400
-msgid " applied to section relative value"
-msgstr " sovellettu lohkosuhteelliseen arvoon"
-
#. Handle binary operators. We use a preprocessor macro as a hack to
#. capture the C operator. KEEP_LEFT means that if the left operand
#. is section relative and the right operand is not, the result uses
@@ -323,75 +424,85 @@ msgstr "ORIGIN on toteuttamatta"
msgid "LENGTH not implemented"
msgstr "LENGTH on toteuttamatta"
-#: fileread.cc:55
+#: fileread.cc:65
#, c-format
msgid "munmap failed: %s"
msgstr "munmap epäonnistui: %s"
-#: fileread.cc:119
+#: fileread.cc:129
#, c-format
msgid "%s: fstat failed: %s"
msgstr "%s: fstat epäonnistui: %s"
-#: fileread.cc:159
+#: fileread.cc:169
#, c-format
msgid "could not reopen file %s"
msgstr "ei voitu avata uudelleen tiedostoa %s"
-#: fileread.cc:292
+#: fileread.cc:302
#, c-format
msgid "%s: pread failed: %s"
msgstr "%s: pread epäonnistui: %s"
-#: fileread.cc:298
+#: fileread.cc:308
#, c-format
msgid "%s: file too short: read only %lld of %lld bytes at %lld"
msgstr "%s: tiedosto on liian lyhyt: lue vain %lld / %lld tavua osoitteesta %lld"
-#: fileread.cc:382
+#: fileread.cc:372
+#, c-format
+msgid "%s: attempt to map %lld bytes at offset %lld exceeds size of file; the file may be corrupt"
+msgstr "%s: yritys kuvata %lld tavua siirrososoitteessa %lld ylittää tiedoston koon; tiedosto on ehkä rikkinäinen"
+
+#: fileread.cc:402
#, c-format
msgid "%s: mmap offset %lld size %lld failed: %s"
msgstr "%s: mmap siirrososoite %lld koko %lld epäonnistui: %s"
-#: fileread.cc:528
+#: fileread.cc:548
#, c-format
msgid "%s: lseek failed: %s"
msgstr "%s: lseek epäonnistui: %s"
-#: fileread.cc:534
+#: fileread.cc:554
#, c-format
msgid "%s: readv failed: %s"
msgstr "%s: readv epäonnistui: %s"
-#: fileread.cc:537
+#: fileread.cc:557
#, c-format
msgid "%s: file too short: read only %zd of %zd bytes at %lld"
msgstr "%s: tiedosto on liian lyhyt: lue vain %zd / %zd tavua osoitteesta %lld"
-#: fileread.cc:686
+#: fileread.cc:706
#, c-format
msgid "%s: total bytes mapped for read: %llu\n"
-msgstr "%s: yhteensä tavuja kartoitettu lukemista varten: %llu\n"
+msgstr "%s: yhteensä tavuja kuvattu lukemista varten: %llu\n"
-#: fileread.cc:688
+#: fileread.cc:708
#, c-format
msgid "%s: maximum bytes mapped for read at one time: %llu\n"
-msgstr "%s: maksimitavuja kartoitettu lukemista varten kerrallaan: %llu\n"
+msgstr "%s: maksimitavuja kuvattu kertalukemista varten: %llu\n"
+
+#: fileread.cc:791
+#, c-format
+msgid "%s: stat failed: %s"
+msgstr "%s: stat epäonnistui: %s"
-#: fileread.cc:783
+#: fileread.cc:849
#, c-format
-msgid "cannot find -l%s"
-msgstr "ei voi löytää -l%s"
+msgid "cannot find %s%s"
+msgstr "ei voi löytää kohdetta %s%s"
-#: fileread.cc:810
+#: fileread.cc:880
#, c-format
msgid "cannot find %s"
-msgstr "ei voi löytää %s"
+msgstr "ei voi löytää kohdetta %s"
-#: fileread.cc:833
+#: fileread.cc:904
#, c-format
msgid "cannot open %s: %s"
-msgstr "ei voi avata %s: %s"
+msgstr "ei voi avata kohdetta %s: %s"
#: gold-threads.cc:103
#, c-format
@@ -418,12 +529,12 @@ msgstr "pthread_mutexattr_destroy epäonnistui: %s"
msgid "pthread_mutex_destroy failed: %s"
msgstr "pthread_mutex_destroy epäonnistui: %s"
-#: gold-threads.cc:131
+#: gold-threads.cc:131 gold-threads.cc:382
#, c-format
msgid "pthread_mutex_lock failed: %s"
msgstr "pthread_mutex_lock epäonnistui: %s"
-#: gold-threads.cc:139
+#: gold-threads.cc:139 gold-threads.cc:394
#, c-format
msgid "pthread_mutex_unlock failed: %s"
msgstr "pthread_mutex_unlock epäonnistui: %s"
@@ -453,124 +564,156 @@ msgstr "pthread_cond_signal epäonnistui: %s"
msgid "pthread_cond_broadcast failed: %s"
msgstr "pthread_cond_broadcast epäonnistui: %s"
-#: gold.cc:83
+#: gold-threads.cc:388
+#, c-format
+msgid "pthread_once failed: %s"
+msgstr "pthread_once epäonnistui: %s"
+
+#: gold.cc:91
#, c-format
msgid "%s: internal error in %s, at %s:%d\n"
msgstr "%s: sisäinen virhe funktiossa %s, tiedostossa %s:%d\n"
-#: gold.cc:130
+#: gold.cc:173
msgid "no input files"
msgstr "ei syötetiedostoja"
-#. We print out just the first .so we see; there may be others.
-#: gold.cc:195
+#: gold.cc:226
+msgid "cannot mix -r with --gc-sections or --icf"
+msgstr "ei voi sekoittaa valitsinta -r valitsimen --gc-sections tai --icf kanssa"
+
+#: gold.cc:407
#, c-format
msgid "cannot mix -static with dynamic object %s"
msgstr "ei voi sekoittaa valitsinta -static dynaamisen objektin %s kanssa"
-#: gold.cc:199
+#: gold.cc:411
#, c-format
msgid "cannot mix -r with dynamic object %s"
msgstr "ei voi sekoittaa valitsinta -r dynaamisen objektin %s kanssa"
-#: gold.cc:203
+#: gold.cc:415
#, c-format
msgid "cannot use non-ELF output format with dynamic object %s"
msgstr "ei voi käyttää ei-ELF-tulostemuotoa dynaamisen objektin %s kanssa"
+#: gold.cc:427
+#, c-format
+msgid "cannot mix split-stack '%s' and non-split-stack '%s' when using -r"
+msgstr "ei voida sekoittaa jaettua pinoa ’%s’ ja ei-jaettua pinoa ’%s’ kun käytetään valitsinta -r"
+
#. FIXME: This needs to specify the location somehow.
-#: i386.cc:193 i386.cc:1588 sparc.cc:211 sparc.cc:2322 x86_64.cc:208
-#: x86_64.cc:1656
+#: i386.cc:232 i386.cc:1669 sparc.cc:234 sparc.cc:2395 x86_64.cc:237
+#: x86_64.cc:1732
msgid "missing expected TLS relocation"
msgstr "puuttuu odotettu TLS-sijoitus"
-#: i386.cc:503 sparc.cc:1066 x86_64.cc:533
-msgid "** PLT"
-msgstr "** PLT"
-
-# Report an unsupported relocation against a local symbol.
-#: i386.cc:843 powerpc.cc:996 sparc.cc:1480 x86_64.cc:921 x86_64.cc:1230
-#, c-format
-msgid "%s: unsupported reloc %u against local symbol"
-msgstr "%s: tukematon sijoitus %u paikallista symbolia kohtaan"
-
-#: i386.cc:907 x86_64.cc:1033
+#: i386.cc:944 x86_64.cc:1068
#, c-format
msgid "section symbol %u has bad shndx %u"
msgstr "lohkosymbolilla %u on virheellinen shndx-lohko %u"
-# These are relocations which ...
-#: i386.cc:965 i386.cc:1297 powerpc.cc:1204 powerpc.cc:1413 sparc.cc:1852
-#: sparc.cc:2204 x86_64.cc:1110 x86_64.cc:1418
-#, c-format
-msgid "%s: unexpected reloc %u in object file"
-msgstr "%s: odottamaton sijoitus %u objektitiedostossa"
-
-#: i386.cc:999 i386.cc:1023 sparc.cc:1753 x86_64.cc:1141 x86_64.cc:1169
+#: i386.cc:1036 i386.cc:1060 sparc.cc:1777 x86_64.cc:1176 x86_64.cc:1204
#, c-format
msgid "local symbol %u has bad shndx %u"
msgstr "paikallisella symbolilla %u on virheellinen shndx-lohko %u"
-# Report an unsupported relocation against a global symbol.
-#: i386.cc:1134 powerpc.cc:1223 sparc.cc:1871 x86_64.cc:1244 x86_64.cc:1536
+#: i386.cc:1991
+msgid "both SUN and GNU model TLS relocations"
+msgstr "sekä SUN- että GNU-mallisia TLS-sijoituksia"
+
+#: i386.cc:2730 x86_64.cc:2719
#, c-format
-msgid "%s: unsupported reloc %u against global symbol %s"
-msgstr "%s: tukematon sijoitus %u yleissymbolia %s kohtaan"
+msgid "failed to match split-stack sequence at section %u offset %0zx"
+msgstr "jaetun pinon täsmääminen epäonnistui lohkossa %u siirros %0zx"
-# Scan relocations for a section.
-#: i386.cc:1473
+#: icf.cc:616
#, c-format
-msgid "%s: unsupported RELA reloc section"
-msgstr "%s: tukematon RELA-sijoituslohko"
+msgid "%s: ICF Converged after %u iteration(s)"
+msgstr "%s: ICF lähentyi %u iteroinnin jälkeen"
-#: i386.cc:1735 i386.cc:2429 powerpc.cc:1740 sparc.cc:2637 x86_64.cc:1859
-#: x86_64.cc:2435
+#: icf.cc:619
#, c-format
-msgid "unexpected reloc %u in object file"
-msgstr "tukematon sijoitus %u objektitiedostossa"
+msgid "%s: ICF stopped after %u iteration(s)"
+msgstr "%s: ICF pysähtyi %u iteroinnin jälkeen"
-#: i386.cc:1767 i386.cc:1846 i386.cc:1898 i386.cc:1929 i386.cc:1986
-#: powerpc.cc:1746 sparc.cc:2643 sparc.cc:2826 sparc.cc:2887 sparc.cc:2994
-#: x86_64.cc:1880 x86_64.cc:1963 x86_64.cc:2018 x86_64.cc:2043
+#: icf.cc:633
#, c-format
-msgid "unsupported reloc %u"
-msgstr "tukematon sijoitus %u"
+msgid "Could not find symbol %s to unfold\n"
+msgstr "Ei voitu löytää symbolia %s paljastettavaksi\n"
-#: i386.cc:1906
-msgid "both SUN and GNU model TLS relocations"
-msgstr "sekä SUN- että GNU-mallisia TLS-sijoituksia"
+#: incremental.cc:242
+#, c-format
+msgid "the link might take longer: cannot perform incremental link: %s"
+msgstr "linkki ei ehkä enää toimi: ei voida suorittaa askelkasvatuslinkitystä: %s"
+
+#: incremental.cc:302
+msgid "no incremental data from previous build"
+msgstr "ei askelkasvatusdataa edellisestä rakentamisesta"
+
+#: incremental.cc:309 incremental.cc:332
+msgid "invalid incremental build data"
+msgstr "virheellinen askelkasvatusrakentamisdata"
+
+#: incremental.cc:321
+msgid "different version of incremental build data"
+msgstr "askelkasvatusrakentamisdatan eri versio"
-#: i386.cc:2443
+#: incremental.cc:338
+msgid "command line changed"
+msgstr "komentorivi vaihtunut"
+
+#: incremental.cc:362
#, c-format
-msgid "unsupported reloc %u in object file"
-msgstr "tukematon sijoitus %u objektitiedostossa"
+msgid "unsupported ELF machine number %d"
+msgstr "tukematon ELF-konenumero %d"
+
+#: incremental.cc:387
+msgid "output is not an ELF file."
+msgstr "tuloste ei ole ELF-tiedosto."
+
+#: incremental.cc:410
+msgid "unsupported file: 32-bit, big-endian"
+msgstr "tukematon tiedosto: 32-bittinen, big-endian"
+
+#: incremental.cc:419
+msgid "unsupported file: 32-bit, little-endian"
+msgstr "tukematon tiedosto: 32-bittinen, little-endian"
-#: layout.cc:1511
+#: incremental.cc:431
+msgid "unsupported file: 64-bit, big-endian"
+msgstr "tukematon tiedosto: 64-bittinen, big-endian"
+
+#: incremental.cc:440
+msgid "unsupported file: 64-bit, little-endian"
+msgstr "tukematon tiedosto: 64-bittinen, little-endian"
+
+#: layout.cc:1887
#, c-format
msgid "--build-id=uuid failed: could not open /dev/urandom: %s"
msgstr "--build-id=uuid epäonnistui: ei voitu avata merkkierikoistiedostoa /dev/urandom: %s"
-#: layout.cc:1518
+#: layout.cc:1894
#, c-format
msgid "/dev/urandom: read failed: %s"
msgstr "/dev/urandom: lukeminen epäonnistui: %s"
-#: layout.cc:1520
+#: layout.cc:1896
#, c-format
msgid "/dev/urandom: expected %zu bytes, got %zd bytes"
msgstr "/dev/urandom: odotettiin %zu tavua, saatiin %zd tavua"
-#: layout.cc:1542
+#: layout.cc:1918
#, c-format
msgid "--build-id argument '%s' not a valid hex number"
msgstr "--build-id argumentti ’%s’ ei ole oikea heksadesimaalinumero"
-#: layout.cc:1548
+#: layout.cc:1924
#, c-format
msgid "unrecognized --build-id argument '%s'"
msgstr "tunnistamaton --build-id argumentti ’%s’"
-#: layout.cc:1866
+#: layout.cc:2337
#, c-format
msgid "load segment overlap [0x%llx -> 0x%llx] and [0x%llx -> 0x%llx]"
msgstr "lataa segmenttilimitys [0x%llx -> 0x%llx] ja [0x%llx -> 0x%llx]"
@@ -578,12 +721,12 @@ msgstr "lataa segmenttilimitys [0x%llx -> 0x%llx] ja [0x%llx -> 0x%llx]"
#: mapfile.cc:70
#, c-format
msgid "cannot open map file %s: %s"
-msgstr "ei voi avata map-tiedostoa %s: %s"
+msgstr "ei voi avata kuvaustiedostoa %s: %s"
#: mapfile.cc:84
#, c-format
msgid "cannot close map file: %s"
-msgstr "ei voi sulkea map-tiedostoa: %s"
+msgstr "ei voi sulkea kuvaustiedostoa: %s"
#: mapfile.cc:116
#, c-format
@@ -620,7 +763,7 @@ msgid ""
"\n"
msgstr ""
"\n"
-"Muistikartta\n"
+"Muistikuvaus\n"
"\n"
#: mapfile.cc:361
@@ -634,185 +777,162 @@ msgstr ""
"Hylätyt syötelohkot\n"
"\n"
-#: merge.cc:449
+#: merge.cc:455
#, c-format
msgid "%s: %s merged constants size: %lu; input: %zu; output: %zu\n"
msgstr "%s: %s yhdistetty vakioiden koko: %lu; syöte: %zu; tuloste: %zu\n"
-#: merge.cc:472
+#: merge.cc:478
msgid "mergeable string section length not multiple of character size"
msgstr "yhdistettävän merkkijonolohkon pituus ei ole merkkikoon monikerta"
-#: merge.cc:488
-msgid "entry in mergeable string section not null terminated"
-msgstr "alkio yhdistettävässä merkkijonolohkossa ei ole null-päätteinen"
+#: merge.cc:494
+#, c-format
+msgid "%s: last entry in mergeable string section '%s' not null terminated"
+msgstr "%s: viimeinen alkio yhdistettävässä merkkijonolohkossa ’%s’ ei ole null-päätteinen"
-#: merge.cc:605
+#: merge.cc:613
#, c-format
msgid "%s: %s input: %zu\n"
msgstr "%s: %s syöte: %zu\n"
-#: merge.h:289
+#: merge.h:300
msgid "** merge constants"
msgstr "** yhdistä vakiot"
-#: merge.h:411
+#: merge.h:422
msgid "** merge strings"
msgstr "** yhdistä merkkijonot"
-#: object.cc:73
+#: object.cc:75
msgid "missing SHT_SYMTAB_SHNDX section"
msgstr "puuttuva SHT_SYMTAB_SHNDX-lohko"
-#: object.cc:117
+#: object.cc:119
#, c-format
msgid "symbol %u out of range for SHT_SYMTAB_SHNDX section"
msgstr "symboli %u lukualueen ulkopuolella lohkolle SHT_SYMTAB_SHNDX"
-#: object.cc:124
+#: object.cc:126
#, c-format
msgid "extended index for symbol %u out of range: %u"
msgstr "laajennettu hakemisto symbolille %u lukualueen ulkopuolella: %u"
-#: object.cc:141
-#, c-format
-msgid "%s: unsupported ELF machine number %d"
-msgstr "%s: tukematon ELF-konenumero %d"
-
-#: object.cc:159
+#: object.cc:148 object.cc:2331 output.cc:4052
#, c-format
msgid "%s: %s"
msgstr "%s: %s"
-#: object.cc:196
+#: object.cc:190
#, c-format
msgid "section name section has wrong type: %u"
msgstr "lohkonimilohko on väärän tyyppinen: %u"
-#: object.cc:459
+#: object.cc:546
#, c-format
msgid "invalid symbol table name index: %u"
msgstr "virheellinen symbolitaulunimi-indeksi: %u"
-#: object.cc:465
+#: object.cc:552
#, c-format
msgid "symbol table name section has wrong type: %u"
msgstr "symbolitaulunimilohko on väärän tyyppinen: %u"
-#: object.cc:554
+#: object.cc:641
#, c-format
msgid "section group %u info %u out of range"
msgstr "lohkoryhmä %u tiedot %u lukualueen ulkopuolella"
-#: object.cc:573
+#: object.cc:660
#, c-format
msgid "symbol %u name offset %u out of range"
msgstr "symbolin %u nimisiirros %u lukualueen ulkopuolella"
-#: object.cc:591
+#: object.cc:678
#, c-format
msgid "symbol %u invalid section index %u"
msgstr "symboli %u virheellinen lohkoindeksi %u"
-#: object.cc:644
+#: object.cc:723
#, c-format
msgid "section %u in section group %u out of range"
msgstr "lohko %u lohkoryhmässä %u lukualueen ulkopuolella"
-#: object.cc:652
+#: object.cc:731
#, c-format
msgid "invalid section group %u refers to earlier section %u"
msgstr "virheellinen lohkoryhmä %u viittaa aikaisempaan lohkoon %u"
-#: object.cc:827 reloc.cc:215 reloc.cc:723
+#: object.cc:1037 reloc.cc:271 reloc.cc:838
#, c-format
msgid "relocation section %u has bad info %u"
-msgstr "uudelleensijoituslohkolla %u on väärät tiedot %u"
+msgstr "sijoituslohkolla %u on väärät tiedot %u"
+
+#: object.cc:1231
+#, c-format
+msgid "%s: removing unused section from '%s' in file '%s'"
+msgstr "%s: poistetaan käyttämättömät lohkot kohteesta ’%s’ tiedostossa ’%s’"
+
+#: object.cc:1257
+#, c-format
+msgid "%s: ICF folding section '%s' in file '%s'into '%s' in file '%s'"
+msgstr "%s: ICF-laskostumislohko ’%s’ tiedostossa ’%s’ kohteeseen ’%s’ tiedostossa ’%s’"
-#: object.cc:1080
+#: object.cc:1454
msgid "size of symbols is not multiple of symbol size"
msgstr "symboleiden koko ei ole symbolikoon monikerta"
-#: object.cc:1187
+#: object.cc:1563
#, c-format
msgid "local symbol %u section name out of range: %u >= %u"
msgstr "paikallisen symbolin %u lohkonimi lukualueen ulkopuolella: %u >= %u"
-#: object.cc:1245
+#: object.cc:1652
#, c-format
msgid "unknown section index %u for local symbol %u"
msgstr "tuntematon lohkoindeksi %u paikalliselle symbolille %u"
-#: object.cc:1254
+#: object.cc:1661
#, c-format
msgid "local symbol %u section index %u out of range"
msgstr "paikallisen symbolin %u lohkoindeksi %u lukualueen ulkopuolella"
-#: object.cc:1619
-msgid "incompatible target"
-msgstr "yhteensopimaton kohde"
-
-#: object.cc:1816
-#, c-format
-msgid "%s: unsupported ELF file type %d"
-msgstr "%s: tukematon ELF-tiedostotyyppi %d"
-
-#: object.cc:1835 object.cc:1881 object.cc:1915
+#: object.cc:2169
#, c-format
-msgid "%s: ELF file too short"
-msgstr "%s: ELF-tiedosto on liian lyhyt"
+msgid "%s is not supported but is required for %s in %s"
+msgstr "%s ei ole tuettu, mutta vaaditaan kohteelle %s kohteessa %s"
-#: object.cc:1843
+#: object.cc:2273
#, c-format
-msgid "%s: invalid ELF version 0"
-msgstr "%s: virheellinen ELF-versio 0"
-
-#: object.cc:1845
-#, c-format
-msgid "%s: unsupported ELF version %d"
-msgstr "%s: tukematon ELF-versio %d"
-
-#: object.cc:1852
-#, c-format
-msgid "%s: invalid ELF class 0"
-msgstr "%s: virheellinen ELF-luokka 0"
-
-#: object.cc:1858
-#, c-format
-msgid "%s: unsupported ELF class %d"
-msgstr "%s: tukematon ELF-luokka %d"
-
-#: object.cc:1865
-#, c-format
-msgid "%s: invalid ELF data encoding"
-msgstr "%s: virheellinen ELF-datakoodaus"
+msgid "%s: unsupported ELF machine number %d"
+msgstr "%s: tukematon ELF-konenumero %d"
-#: object.cc:1871
+#: object.cc:2283
#, c-format
-msgid "%s: unsupported ELF data encoding %d"
-msgstr "%s: tukematon ELF-datakoodaus %d"
+msgid "%s: incompatible target"
+msgstr "%s: yhteensopimaton kohde"
-#: object.cc:1891
+#: object.cc:2347 plugin.cc:1019
#, c-format
msgid "%s: not configured to support 32-bit big-endian object"
msgstr "%s: ei ole asetettu tukemaan 32-bittistä big-endian-objektia"
-#: object.cc:1904
+#: object.cc:2363 plugin.cc:1028
#, c-format
msgid "%s: not configured to support 32-bit little-endian object"
msgstr "%s: ei ole asetettu tukemaan 32-bittistä little-endian-objektia"
-#: object.cc:1925
+#: object.cc:2382 plugin.cc:1040
#, c-format
msgid "%s: not configured to support 64-bit big-endian object"
msgstr "%s: ei ole asetettu tukemaan 64-bittistä big-endian-objektia"
-#: object.cc:1938
+#: object.cc:2398 plugin.cc:1049
#, c-format
msgid "%s: not configured to support 64-bit little-endian object"
msgstr "%s: ei ole asetettu tukemaan 64-bittistä little-endian-objektia"
-#: options.cc:142
+#: options.cc:156
#, c-format
msgid ""
"Usage: %s [options] file...\n"
@@ -823,1036 +943,1294 @@ msgstr ""
#. config.guess and libtool.m4 look in ld --help output for the
#. string "supported targets".
-#: options.cc:150
+#: options.cc:164
#, c-format
msgid "%s: supported targets:"
msgstr "%s: tuetut kohteet:"
-#: options.cc:162
+#: options.cc:176
#, c-format
msgid "Report bugs to %s\n"
msgstr ""
"Ilmoita virheistä (englanniksi) osoitteeseen %s\n"
"Ilmoita suomennosvirheistä osoitteeseen <translation-team-fi@lists.sourceforge.net>\n"
-#: options.cc:179 options.cc:189
+#: options.cc:193 options.cc:203 options.cc:213
#, c-format
msgid "%s: invalid option value (expected an integer): %s"
msgstr "%s: virheellinen valitsinarvo (odotettiin kokonaislukua): %s"
-#: options.cc:199
+#: options.cc:223
#, c-format
msgid "%s: invalid option value (expected a floating point number): %s"
msgstr "%s: virheellinen valitsinarvo (odotettiin liukulukunumeroa): %s"
-#: options.cc:208
+#: options.cc:232
#, c-format
msgid "%s: must take a non-empty argument"
msgstr "%s: täytyy olla ei-tyhjä argumentti"
-#: options.cc:249
+#: options.cc:273
#, c-format
msgid "%s: must take one of the following arguments: %s"
msgstr "%s: täytyy olla yksi seuraavista argumenteista: %s"
-#: options.cc:275
+#: options.cc:300
#, c-format
msgid " Supported targets:\n"
msgstr " Tuetut kohteet:\n"
-#: options.cc:329
+#: options.cc:409
#, c-format
msgid "unable to parse script file %s"
msgstr "ei kyetä jäsentämään skriptitiedostoa %s"
-#: options.cc:337
+#: options.cc:417
#, c-format
msgid "unable to parse version script file %s"
msgstr "ei kyetä jäsentämään versioskriptitiedostoa %s"
-#: options.cc:363
+#: options.cc:425
+#, c-format
+msgid "unable to parse dynamic-list script file %s"
+msgstr "ei kyetä jäsentämään dynaamisluetteloista skriptitiedostoa %s"
+
+#: options.cc:522
+#, c-format
+msgid "format '%s' not supported; treating as elf (supported formats: elf, binary)"
+msgstr "muotoa ’%s’ ei tueta; käsitellään elf-objektina (tuetut muodot: elf, binaari)"
+
+#: options.cc:538
#, c-format
msgid "%s: use the --help option for usage information\n"
msgstr "%s: käytä valitsinta --help käyttötietojen saamiseksi\n"
-#: options.cc:372
+#: options.cc:547
#, c-format
msgid "%s: %s: %s\n"
msgstr "%s: %s: %s\n"
-#: options.cc:393
-#, c-format
-msgid "format '%s' not supported; treating as elf (supported formats: elf, binary)"
-msgstr "muotoa ’%s’ ei tueta; käsitellään elf-objektina (tuetut muodot: elf, binääri)"
-
-#: options.cc:499
+#: options.cc:651
msgid "unexpected argument"
msgstr "odottamaton argumentti"
-#: options.cc:512 options.cc:573
+#: options.cc:664 options.cc:725
msgid "missing argument"
msgstr "puuttuva argumentti"
-#: options.cc:584
+#: options.cc:736
msgid "unknown -z option"
msgstr "tuntematon valitsin -z"
-#: options.cc:727
+#: options.cc:935
#, c-format
msgid "ignoring --threads: %s was compiled without thread support"
msgstr "ei oteta huomioon valitsinta --threads: %s käännettiin ilman säietukea"
-#: options.cc:734
+#: options.cc:942
#, c-format
msgid "ignoring --thread-count: %s was compiled without thread support"
msgstr "ohitetaan --thread-count: %s käännettiin ilman säietukea"
-#: options.cc:776
+#: options.cc:981
+#, c-format
+msgid "unable to open -retain-symbols-file file %s: %s"
+msgstr "ei kyetä avaamaan -retain-symbols-file -tiedostoa %s: %s"
+
+#: options.cc:1003
+msgid "-shared and -static are incompatible"
+msgstr "valitsimet -shared ja -static ovat yhteensopimattomat"
+
+#: options.cc:1005
+msgid "-shared and -pie are incompatible"
+msgstr "valitsimet -shared ja -pie ovat yhteensopimattomat"
+
+#: options.cc:1008
msgid "-shared and -r are incompatible"
msgstr "valitsimet -shared ja -r ovat yhteensopimattomat"
-#: options.cc:780
-msgid "binary output format not compatible with -shared or -r"
-msgstr "binääritulostemuoto ei ole yhteensopiva valitsimien -shared tai -r kanssa"
+#: options.cc:1010
+msgid "-pie and -r are incompatible"
+msgstr "valitsimet -pie ja -r ovat yhteensopimattomat"
+
+#: options.cc:1014
+msgid "-retain-symbols-file does not yet work with -r"
+msgstr "-retain-symbols-file ei vielä toimi valitsimen -r kanssa"
+
+#: options.cc:1020
+msgid "binary output format not compatible with -shared or -pie or -r"
+msgstr "binaaritulostemuoto ei ole yhteensopiva valitsimien -shared, -pie tai -r kanssa"
-#: options.cc:785
+#: options.cc:1026
#, c-format
msgid "--hash-bucket-empty-fraction value %g out of range [0.0, 1.0)"
msgstr "--hash-bucket-empty-fraction arvo %g lukualueen ulkopuolella [0.0, 1.0)"
-#: options.cc:852
+#: options.cc:1031
+msgid "Options --incremental-changed, --incremental-unchanged, --incremental-unknown require the use of --incremental"
+msgstr "Valitsimet --incremental-changed, --incremental-unchanged, --incremental-unknown vaativat valitsimen --incremental käytön"
+
+#: options.cc:1097
msgid "May not nest groups"
msgstr "Ei saa sisäkkäistää ryhmiä"
-#: options.cc:864
+#: options.cc:1109
msgid "Group end without group start"
msgstr "Ryhmäloppu ilman ryhmäalkua"
#. I guess it's neither a long option nor a short option.
-#: options.cc:922
+#: options.cc:1174
msgid "unknown option"
msgstr "tuntematon valitsin"
-#: options.cc:948
+#: options.cc:1201
#, c-format
msgid "%s: missing group end\n"
msgstr "%s: puuttuva ryhmäloppu\n"
-#: options.h:536
+#: options.h:571
msgid "Report usage information"
msgstr "Ilmoita käyttötiedot"
-#: options.h:538
+#: options.h:573
msgid "Report version information"
msgstr "Ilmoita versiotiedot"
-#: options.h:540
+#: options.h:575
msgid "Report version and target information"
msgstr "Ilmoita versio- ja kohdetiedot"
-#: options.h:549
+#: options.h:584 options.h:635
+msgid "Not supported"
+msgstr "Ei tuettu"
+
+#: options.h:585 options.h:636
+msgid "Do not copy DT_NEEDED tags from shared libraries"
+msgstr "Älä kopioi DT_NEEDED-tunnisteita jaettuihin kirjastoihin"
+
+#: options.h:588
msgid "Allow unresolved references in shared libraries"
msgstr "Salli ratkaisemattomat viitteet jaettuihin kirjastoihin"
-#: options.h:550
+#: options.h:589
msgid "Do not allow unresolved references in shared libraries"
msgstr "Älä salli ratkaisemattomia viitteitä jaettuihin kirjastoihin"
-#: options.h:553
-msgid "Only set DT_NEEDED for dynamic libs if used"
-msgstr "Aseta DT_NEEDED dynaamisille kirjastoille vain jos käytetty"
+#: options.h:592
+msgid "Only set DT_NEEDED for shared libraries if used"
+msgstr "Aseta DT_NEEDED jaetuille kirjastoille vain jos käytetty"
-#: options.h:554
-msgid "Always DT_NEEDED for dynamic libs"
-msgstr "Aina DT_NEEDED dynaamisille kirjastoille"
+#: options.h:593
+msgid "Always DT_NEEDED for shared libraries"
+msgstr "Aina DT_NEEDED jaetuille kirjastoille"
-#: options.h:561
+#: options.h:600
msgid "Set input format"
msgstr "Aseta syötemuoto"
-#: options.h:564
+#: options.h:603
msgid "-l searches for shared libraries"
msgstr "-l etsii jaettuja kirjastoja"
-#: options.h:566
+#: options.h:605
msgid "-l does not search for shared libraries"
msgstr "-l ei etsi jaettuja kirjastoja"
-#: options.h:570
+#: options.h:609
msgid "Bind defined symbols locally"
msgstr "Sido määritellyt symbolit paikallisesti"
-#: options.h:573
+#: options.h:612
msgid "Bind defined function symbols locally"
msgstr "Sido määritellyt funktiosymbolit paikallisesti"
-#: options.h:576
+#: options.h:615
msgid "Generate build ID note"
msgstr "Tuota rakentamistunnisteilmoitus"
-#: options.h:577 options.h:612
+#: options.h:616 options.h:655
msgid "[=STYLE]"
msgstr "[=TYYLI]"
-#: options.h:580
+#: options.h:619
msgid "Check segment addresses for overlaps (default)"
msgstr "Tarkista segmenttiosoitteet päällekkäisyyksien varalta (oletus)"
-#: options.h:581
+#: options.h:620
msgid "Do not check segment addresses for overlaps"
msgstr "Älä tarkista segmenttiosoitteiden päällekkäisyyksiä"
-#: options.h:585 options.h:590
+#: options.h:624 options.h:629
msgid "Compress .debug_* sections in the output file"
msgstr "Tiivistä .debug_* -lohkot tulostetiedostossa"
-#: options.h:591
+#: options.h:630
msgid "[none]"
msgstr "[ei mitään]"
-#: options.h:596
+#: options.h:639
msgid "Define common symbols"
msgstr "Anna yhteissymbolit"
-#: options.h:597
+#: options.h:640
msgid "Do not define common symbols"
msgstr "Älä anna yhteissymboleja"
-#: options.h:599 options.h:601
+#: options.h:642 options.h:644
msgid "Alias for -d"
msgstr "Alias valitsimelle -d"
-#: options.h:604
+#: options.h:647
msgid "Turn on debugging"
msgstr "Käännä päälle vianjäljitys"
-#: options.h:605
+#: options.h:648
msgid "[all,files,script,task][,...]"
msgstr "[kaikki,tiedostot,skripti,tehtävä][,...]"
-#: options.h:608
+#: options.h:651
msgid "Define a symbol"
msgstr "Määrittele symboli"
-#: options.h:608
+#: options.h:651
msgid "SYMBOL=EXPRESSION"
msgstr "SYMBOLI=LAUSEKE"
-#: options.h:611
+#: options.h:654
msgid "Demangle C++ symbols in log messages"
msgstr "Elvytä C++ -symbolit lokiviesteissä"
-#: options.h:615
+#: options.h:658
msgid "Do not demangle C++ symbols in log messages"
msgstr "Älä elvytä C++ -symboleja lokiviesteissä"
-#: options.h:619
+#: options.h:662
msgid "Try to detect violations of the One Definition Rule"
msgstr "Yritä havaita yhden määrittelysäännön rikkomukset"
-#: options.h:623
+#: options.h:666
+msgid "Delete all temporary local symbols"
+msgstr "Poista kaikki tilapäiset paikalliset symbolit"
+
+#: options.h:669
+msgid "Add data symbols to dynamic symbols"
+msgstr "Lisää datasymbolit dynaamisiin symboleihin"
+
+#: options.h:672
+msgid "Add C++ operator new/delete to dynamic symbols"
+msgstr "Lisää C++-operaattori new/delete dynaamisiin symboleihin"
+
+#: options.h:675
+msgid "Add C++ typeinfo to dynamic symbols"
+msgstr "Lisää C++-typeinfo dynaamisiin symboleihin"
+
+#: options.h:678
+msgid "Read a list of dynamic symbols"
+msgstr "Lue dynaamisten symbolien luettelo"
+
+#: options.h:678 options.h:732 options.h:766 options.h:893 options.h:921
+msgid "FILE"
+msgstr "TIEDOSTO"
+
+#: options.h:681
msgid "Set program start address"
msgstr "Aseta ohjelman aloitusosoite"
-#: options.h:623 options.h:766 options.h:768 options.h:770
+#: options.h:681 options.h:908 options.h:910 options.h:912
msgid "ADDRESS"
msgstr "OSOITE"
-#: options.h:626
+#: options.h:684
+msgid "Exclude libraries from automatic export"
+msgstr "Jätä kirjastot pois automaattisesta viennistä"
+
+#: options.h:688
msgid "Export all dynamic symbols"
msgstr "Vie kaikki dynaamiset symbolit"
-#: options.h:629
+#: options.h:689
+msgid "Do not export all dynamic symbols (default)"
+msgstr "Älä vie kaikkia dynaamisia symboleita (oletus)"
+
+#: options.h:692
msgid "Create exception frame header"
msgstr "Luo poikkeuskehysotsake"
-#: options.h:632
+#: options.h:695
msgid "Treat warnings as errors"
msgstr "Käsittele varoituksia virheinä"
-#: options.h:633
+#: options.h:696
msgid "Do not treat warnings as errors"
msgstr "Älä käsittele varoituksia virheinä"
-#: options.h:636
+#: options.h:699
+msgid "Call SYMBOL at unload-time"
+msgstr "Kutsu SYMBOLIa sulkemishetkellä"
+
+#: options.h:699 options.h:729 options.h:873 options.h:915 options.h:936
+#: options.h:939
+msgid "SYMBOL"
+msgstr "SYMBOLI"
+
+#: options.h:702
msgid "Set shared library name"
msgstr "Aseta jaettu kirjastonimi"
-#: options.h:636 options.h:696
+#: options.h:702 options.h:792
msgid "FILENAME"
msgstr "TIEDOSTONIMI"
-#: options.h:639
+#: options.h:705
msgid "Min fraction of empty buckets in dynamic hash"
msgstr "Tyhjien lohkojen pienin murto-osa dynaamisessa hash-funktiossa"
-#: options.h:640
+#: options.h:706
msgid "FRACTION"
-msgstr "FRACTION"
+msgstr "MURTO-OSA"
-#: options.h:643
+#: options.h:709
msgid "Dynamic hash style"
msgstr "Dynaaminen hash-tyyli"
-#: options.h:643
+#: options.h:709
msgid "[sysv,gnu,both]"
msgstr "[sysv,gnu,both]"
-#: options.h:647
+#: options.h:713
msgid "Set dynamic linker path"
msgstr "Aseta dynaaminen linkittäjäpolku"
-#: options.h:647
+#: options.h:713
msgid "PROGRAM"
msgstr "OHJELMA"
-#: options.h:650
+#: options.h:716
+msgid "Work in progress; do not use"
+msgstr "Työ käynnissä; älä käytä"
+
+#: options.h:717
+msgid "Do a full build"
+msgstr "Tee täysi rakentaminen"
+
+#: options.h:720
+msgid "Assume files changed"
+msgstr "Otaksu tiedostojen muuttuneen"
+
+#: options.h:723
+msgid "Assume files didn't change"
+msgstr "Otaksu, että tiedostot eivät ole muuttuneet"
+
+#: options.h:726
+msgid "Use timestamps to check files (default)"
+msgstr "Käytä aikaleimoja tiedostojen tarkistamiseen (oletus)"
+
+#: options.h:729
+msgid "Call SYMBOL at load-time"
+msgstr "Kutsu SYMBOLIa latausaikana"
+
+#: options.h:732
msgid "Read only symbol values from FILE"
msgstr "Lue vain symboliarvot TIEDOSTOsta"
-#: options.h:650 options.h:684 options.h:751 options.h:779
-msgid "FILE"
-msgstr "TIEDOSTO"
-
-#: options.h:653
+#: options.h:735
msgid "Search for library LIBNAME"
msgstr "Haku kirjastolle LIBNAME"
-#: options.h:653
+#: options.h:735
msgid "LIBNAME"
msgstr "LIBNAME"
-#: options.h:656
+#: options.h:738
msgid "Add directory to search path"
msgstr "Lisää hakemisto hakupolkuun"
-#: options.h:656 options.h:714 options.h:717 options.h:721 options.h:745
+#: options.h:738 options.h:813 options.h:816 options.h:820 options.h:887
msgid "DIR"
msgstr "DIR"
-#: options.h:659
+#: options.h:741
msgid "Ignored for compatibility"
msgstr "Ei oteta huomioon yhteensopivuussyistä"
-#: options.h:659
+#: options.h:741
msgid "EMULATION"
msgstr "EMULOINTI"
-#: options.h:662
+#: options.h:744
msgid "Write map file on standard output"
-msgstr "Kirjoita karttatiedosto vakiotulosteeseen"
+msgstr "Kirjoita kuvaustiedosto vakiotulosteeseen"
-#: options.h:663
+#: options.h:745
msgid "Write map file"
-msgstr "Kirjoita map-tiedosto"
+msgstr "Kirjoita kuvaustiedosto"
-#: options.h:664
+#: options.h:746
msgid "MAPFILENAME"
-msgstr "MAPFILENAME"
+msgstr "KUVAUSTIEDOSTONIMI"
-#: options.h:667
+#: options.h:749
msgid "Do not page align data"
msgstr "Älä tasaa dataa sivun kokoisiin osiin"
-#: options.h:669
+#: options.h:751
msgid "Do not page align data, do not make text readonly"
msgstr "Älä tasaa dataa sivun kokoisiin osiin, älä kirjoitussuojaa tekstiä"
-#: options.h:670
+#: options.h:752
msgid "Page align data, make text readonly"
msgstr "Sivutasausdataa, tee tekstistä kirjoitussuojattu"
-#: options.h:673
+#: options.h:755
msgid "Enable use of DT_RUNPATH and DT_FLAGS"
msgstr "Ota käyttöön DT_RUNPATH-hakemistot ja DT_FLAGS-liput"
-#: options.h:674
+#: options.h:756
msgid "Disable use of DT_RUNPATH and DT_FLAGS"
msgstr "Ota pois käytöstä DT_RUNPATH-hakemistot ja DT_FLAGS-liput"
-#: options.h:677
+#: options.h:759
msgid "Create an output file even if errors occur"
msgstr "Luo tulostetiedosto myös silloin kun tapahtuu virhe"
-#: options.h:680 options.h:808
+#: options.h:762 options.h:958
msgid "Report undefined symbols (even with --shared)"
msgstr "Ilmoita määrittelemättömistä symboleista (jopa valitsimella --shared)"
-#: options.h:684
+#: options.h:766
msgid "Set output file name"
msgstr "Aseta tulostetiedostonimi"
-#: options.h:687
+#: options.h:769
msgid "Optimize output file size"
msgstr "Optimoi tulostetiedostokoko"
-#: options.h:687
+#: options.h:769
msgid "LEVEL"
msgstr "TASO"
-#: options.h:690
+#: options.h:772
msgid "Set output format"
msgstr "Aseta tulostusmuoto"
-#: options.h:690
+#: options.h:772
msgid "[binary]"
msgstr "[binaari]"
-#: options.h:693
+#: options.h:775 options.h:777
+msgid "Create a position independent executable"
+msgstr "Luo paikkariippumaton suoritettava tiedosto"
+
+#: options.h:782
+msgid "Load a plugin library"
+msgstr "Lataa lisäosakirjasto"
+
+#: options.h:782
+msgid "PLUGIN"
+msgstr "LISÄOSA"
+
+#: options.h:784
+msgid "Pass an option to the plugin"
+msgstr "Välitä valitsin lisäosalle"
+
+#: options.h:784
+msgid "OPTION"
+msgstr "VALITSIN"
+
+#: options.h:788
msgid "Preread archive symbols when multi-threaded"
msgstr "Ennakkoluetut arkistosymbolit monisäikeitä käytettäessä"
-#: options.h:695
+#: options.h:791
msgid "Print symbols defined and used for each input"
msgstr "Tulosta jokaiselle syötteelle määritellyt ja käytetyt symbolit"
-#: options.h:699
+#: options.h:795
msgid "Ignored for SVR4 compatibility"
msgstr "Älä ota huomioon SVR4-yhteensopivuutta"
-#: options.h:702
+#: options.h:798
msgid "Generate relocations in output"
-msgstr "Luo sijoitukset tulosteeseen"
+msgstr "Tuota sijoitukset tulosteeseen"
-#: options.h:705
+#: options.h:801
msgid "Generate relocatable output"
-msgstr "Tuota uudelleensijoitettava tuloste"
+msgstr "Tuota sijoitettava tuloste"
-#: options.h:708
+#: options.h:804
msgid "Relax branches on certain targets"
msgstr "Relax-projektin haarat tietyissä kohteissa"
-#: options.h:714 options.h:717
+#: options.h:807
+msgid "keep only symbols listed in this file"
+msgstr "pidä vain tässä tiedostossa luetellut symbolit"
+
+#: options.h:807
+msgid "[file]"
+msgstr "[tiedosto]"
+
+#: options.h:813 options.h:816
msgid "Add DIR to runtime search path"
msgstr "Lisää DIR ajoaikaiseen hakupolkuun"
-#: options.h:720
+#: options.h:819
msgid "Add DIR to link time shared library search path"
msgstr "Lisää DIR linkitysaikana jaettuun kirjastohakupolkuun"
-#: options.h:724
+#: options.h:823
msgid "Strip all symbols"
msgstr "Riisu kaikki symbolit"
-#: options.h:726
+#: options.h:825
msgid "Strip debugging information"
msgstr "Riisu vianjäljitystiedot"
-#: options.h:728
+#: options.h:827
msgid "Emit only debug line number information"
msgstr "Lähetä vain vianjäljitysrivinumerotiedot"
-#: options.h:730
+#: options.h:829
msgid "Strip debug symbols that are unused by gdb (at least versions <= 6.7)"
msgstr "Riisu vianjäljityssymbolit, joita gdb ei käytä (vähintään versioissa <= 6.7)"
-#: options.h:734
+#: options.h:832
+msgid "Strip LTO intermediate code sections"
+msgstr "Riisu LTO-keskikoodilohkot"
+
+#: options.h:835
+msgid "(ARM only) The maximum distance from instructions in a group of sections to their stubs. Negative values mean stubs are always after the group. 1 means using default size.\n"
+msgstr "(vain ARM) Käskyjen enimmäisetäisyys niiden stub-koodeihin lohkojen ryhmässä. Negatiiviset arvot tarkoittavat, että stub-koodit ovat ryhmän jäljessä. 1 tarkoittaa oletuskokoa.\n"
+
+#: options.h:838 options.h:852 options.h:956 options.h:975
+msgid "SIZE"
+msgstr "KOKO"
+
+#: options.h:841
+msgid "Use less memory and more disk I/O (included only for compatibility with GNU ld)"
+msgstr "Käytä vähemmän muistia ja enemmän levysiirräntää (sisällytetty GNU ld -yhteensopivuussyistä)"
+
+#: options.h:845 options.h:848
msgid "Generate shared library"
msgstr "Tuota jaettu kirjasto"
-#: options.h:739
+#: options.h:851
+msgid "Stack size when -fsplit-stack function calls non-split"
+msgstr "Pinokoko kun -fsplit-stack -funktio kutsuu non-split -pinoa"
+
+#: options.h:857
msgid "Do not link against shared libraries"
msgstr "Älä linkitä jaettuihin kirjastoihin"
-#: options.h:742
+#: options.h:860
+msgid "Identical Code Folding. '--icf=safe' folds only ctors and dtors."
+msgstr "Identtinen koodilaskostuminen. ’--icf=safe’ laskostaa vain kohteet ctors ja dtors."
+
+#: options.h:866
+msgid "Number of iterations of ICF (default 2)"
+msgstr "ICF-iterointien lukumäärä (oletus 2)"
+
+#: options.h:866 options.h:899 options.h:901 options.h:903 options.h:905
+msgid "COUNT"
+msgstr "LASKURI"
+
+#: options.h:869
+msgid "List folded identical sections on stderr"
+msgstr "Luettele laskostetut identtiset lohkot vakiovirheessä"
+
+#: options.h:870
+msgid "Do not list folded identical sections"
+msgstr "Älä luettele laskostettuja identtisiä lohkoja"
+
+#: options.h:873
+msgid "Do not fold this symbol during ICF"
+msgstr "Älä laskosta tätä symbolia ICF:n aikana"
+
+#: options.h:876
+msgid "Remove unused sections"
+msgstr "Poista käyttämättömät lohkot"
+
+#: options.h:877
+msgid "Don't remove unused sections (default)"
+msgstr "Älä poista käyttämättömiä lohkoja (oletus)"
+
+#: options.h:880
+msgid "List removed unused sections on stderr"
+msgstr "Luettele poistetut käyttämättömät lohkot vakiovirheessä"
+
+#: options.h:881
+msgid "Do not list removed unused sections"
+msgstr "Älä luettele poistettuja käyttämättömiä lohkoja"
+
+#: options.h:884
msgid "Print resource usage statistics"
msgstr "Tulosta resurssikäyttötilastot"
-#: options.h:745
+#: options.h:887
msgid "Set target system root directory"
msgstr "Aseta kohdejärjestelmän juurihakemisto"
-#: options.h:748
+#: options.h:890
msgid "Print the name of each input file"
msgstr "Tulosta jokaisen syötetiedoston nimi"
-#: options.h:751
+#: options.h:893
msgid "Read linker script"
msgstr "Lue linkkeriskripti"
-#: options.h:754
+#: options.h:896
msgid "Run the linker multi-threaded"
msgstr "Suorita linkkeri monisäikeisesti"
-#: options.h:755
+#: options.h:897
msgid "Do not run the linker multi-threaded"
msgstr "Älä suorita linkkeriä monisäikeisesti"
-#: options.h:757
+#: options.h:899
msgid "Number of threads to use"
msgstr "Käytettävien säikeiden lukumäärä"
-#: options.h:757 options.h:759 options.h:761 options.h:763
-msgid "COUNT"
-msgstr "LASKURI"
-
-#: options.h:759
+#: options.h:901
msgid "Number of threads to use in initial pass"
msgstr "Alustavassa ajossa käytettyjen säikeiden lukumäärä"
-#: options.h:761
+#: options.h:903
msgid "Number of threads to use in middle pass"
msgstr "Keskimmäisessä ajossa käytettyjen säikeiden lukumäärä"
-#: options.h:763
+#: options.h:905
msgid "Number of threads to use in final pass"
msgstr "Lopullisessa ajossa käytettyjen säikeiden lukumäärä"
-#: options.h:766
+#: options.h:908
msgid "Set the address of the bss segment"
msgstr "Aseta bss-lohkon osoite"
-#: options.h:768
+#: options.h:910
msgid "Set the address of the data segment"
msgstr "Aseta data-segmentin osoite"
-#: options.h:770
+#: options.h:912
msgid "Set the address of the text segment"
msgstr "Aseta text-segmentin osoite"
-#: options.h:773
+#: options.h:915
msgid "Create undefined reference to SYMBOL"
msgstr "Luo määrittelemätön viite SYMBOLIin"
-#: options.h:773 options.h:786 options.h:789
-msgid "SYMBOL"
-msgstr "SYMBOLI"
-
-#: options.h:776
+#: options.h:918
msgid "Synonym for --debug=files"
msgstr "Synonyymi valitsimelle --debug=tiedostot"
-#: options.h:779
+#: options.h:921
msgid "Read version script"
msgstr "Lue versioskripti"
-#: options.h:782
+#: options.h:924
+msgid "Warn about duplicate common symbols"
+msgstr "Varoita yhteissymbolien kaksoiskappaleista"
+
+#: options.h:925
+msgid "Do not warn about duplicate common symbols (default)"
+msgstr "Älä varoita yhteissymbolien kaksoiskappaleista (oletus)"
+
+#: options.h:928
+msgid "Warn when skipping an incompatible library"
+msgstr "Varoita, kun ohitetaan yhteensopimaton kirjasto"
+
+#: options.h:929
+msgid "Don't warn when skipping an incompatible library"
+msgstr "Älä varoita, kun ohitetaan yhteensopimaton kirjasto"
+
+#: options.h:932
msgid "Include all archive contents"
msgstr "Sisällytä kaikki arkistosisällöt"
-#: options.h:783
+#: options.h:933
msgid "Include only needed archive contents"
msgstr "Sisällytä vain tarvitut arkistosisällöt"
-#: options.h:786
+#: options.h:936
msgid "Use wrapper functions for SYMBOL"
msgstr "Käytä käärinfunktioita symbolille SYMBOLI"
-#: options.h:789
+#: options.h:939
msgid "Trace references to symbol"
msgstr "Jäljitä viitteet symboliin"
-#: options.h:792
+#: options.h:942
msgid "Default search path for Solaris compatibility"
msgstr "Oletushakupolku Solaris-yhteensopivuutta varten"
-#: options.h:793
+#: options.h:943
msgid "PATH"
msgstr "POLKU"
-#: options.h:796
+#: options.h:946
msgid "Start a library search group"
msgstr "Aloita kirjastonetsimisryhmä"
-#: options.h:798
+#: options.h:948
msgid "End a library search group"
msgstr "Lopeta kirjastonetsimisryhmä"
-#: options.h:803
+#: options.h:953
msgid "Sort dynamic relocs"
msgstr "Lajittele dynaamiset relocs-tietueet"
-#: options.h:804
+#: options.h:954
msgid "Do not sort dynamic relocs"
msgstr "Älä lajittele dynaamisia relocs-tietueita"
-#: options.h:806
+#: options.h:956
msgid "Set common page size to SIZE"
msgstr "Aseta yhteissivun kooksi KOKO"
-#: options.h:806 options.h:813
-msgid "SIZE"
-msgstr "KOKO"
-
-#: options.h:811
+#: options.h:961
msgid "Mark output as requiring executable stack"
msgstr "Merkitse tuloste vaadittuna suoritettavassa pinossa"
-#: options.h:813
-msgid "Set maximum page size to SIZE"
-msgstr "Aseta suurimmaksi sivukooksi KOKO"
-
-#: options.h:815
-msgid "Mark output as not requiring executable stack"
-msgstr "Merkitse, että tuloste ei vaadi suoritettavaa pinoa"
-
# DSO on ilmeisesti Dynamic shared object
-#: options.h:817
+#: options.h:963
msgid "Mark DSO to be initialized first at runtime"
msgstr "Merkitse dynaamisesti jaetut objektit alustettavaksi ensimmäiseksi ajoaikana"
-#: options.h:820
+#: options.h:966
msgid "Mark object to interpose all DSOs but executable"
msgstr "Merkitse objekti kaikkien dynaamisesti jaettujen objektien väliin paitsi suoritettavien"
-#: options.h:823
+#: options.h:969
+msgid "Mark object for lazy runtime binding (default)"
+msgstr "Merkitse objekti lazy-ajoaikaista sidontaa varten (oletus)"
+
+#: options.h:972
msgid "Mark object requiring immediate process"
msgstr "Merkitse, että objekti vaatii välitöntä käsittelyä"
-#: options.h:826
+#: options.h:975
+msgid "Set maximum page size to SIZE"
+msgstr "Aseta suurimmaksi sivukooksi KOKO"
+
+#: options.h:978
+msgid "Do not create copy relocs"
+msgstr "Älä luo kopio-relocs-tietueita"
+
+#: options.h:980
msgid "Mark object not to use default search paths"
msgstr "Merkitse, että objekti ei käytä oletushakupolkuja"
-#: options.h:829
+#: options.h:983
msgid "Mark DSO non-deletable at runtime"
msgstr "Merkitse dynaamisesti jaettu objekti ei-poistettavaksi ajoaikana"
-#: options.h:832
+#: options.h:986
msgid "Mark DSO not available to dlopen"
msgstr "Merkitse, että dynaamisesti jaettu objekti ei ole saatavilla funktiolle dlopen"
-#: options.h:835
+#: options.h:989
msgid "Mark DSO not available to dldump"
msgstr "Merkitse, että dynaamisesti jaettu objekti ei saatavilla funktiolle dldump"
-#: options.h:838
+#: options.h:992
+msgid "Mark output as not requiring executable stack"
+msgstr "Merkitse, että tuloste ei vaadi suoritettavaa pinoa"
+
+#: options.h:994
+msgid "Mark object for immediate function binding"
+msgstr "Merkitse, että objekti vaatii välitöntä funktion sidontaa"
+
+#: options.h:997
+msgid "Mark DSO to indicate that needs immediate $ORIGIN processing at runtime"
+msgstr "Merkitse DSO osoittamaan, että se tarvitsee välittömän $ORIGIN-käsittelyn ajoaikaisesti"
+
+#: options.h:1000
msgid "Where possible mark variables read-only after relocation"
-msgstr "Missä mahdollista, merkitse muuttuja kirjoitussuojatuiksi uudelleensijoituksen jälkeen"
+msgstr "Missä mahdollista, merkitse muuttuja kirjoitussuojatuiksi sijoituksen jälkeen"
-#: options.h:839
+#: options.h:1001
msgid "Don't mark variables read-only after relocation"
msgstr "Älä merkitse muuttujia kirjoitussuojatuiksi siirroksen jälkeen"
-#: output.cc:1098
+#: output.cc:1132
msgid "section group retained but group element discarded"
msgstr "lohkoryhmä palautettu, mutta ryhmän elementti hylätty"
-#: output.cc:1800
+#: output.cc:1860
#, c-format
msgid "invalid alignment %lu for section \"%s\""
msgstr "virheellinen tasaus %lu lohkolle ”%s”"
-#: output.cc:3159
+#: output.cc:3573
+#, c-format
+msgid "dot moves backward in linker script from 0x%llx to 0x%llx"
+msgstr "piste siirtyy taaksepäin linkkeriskriptissä osoitteesta 0x%llx osoitteeseen 0x%llx"
+
+#: output.cc:3576
+#, c-format
+msgid "address of section '%s' moves backward from 0x%llx to 0x%llx"
+msgstr "lohkon ’%s’ osoite siirtyy taaksepäin osoitteesta 0x%llx osoitteeseen 0x%llx"
+
+#: output.cc:3755
#, c-format
msgid "nobits section %s may not precede progbits section %s in same segment"
msgstr "nobits-lohko %s ei voi edeltää progbits-lohkoa %s samassa segmentissä"
-#: output.cc:3329
+#: output.cc:3907 output.cc:3975
#, c-format
msgid "%s: open: %s"
msgstr "%s: avaa tiedosto: %s"
-#: output.cc:3350
+#: output.cc:3996
#, c-format
msgid "%s: mremap: %s"
msgstr "%s: mremap epäonnistui: %s"
-# Tätä ei löydy enää lähdekoodista
-#: output.cc:3387
-#, c-format
-msgid "%s: lseek: %s"
-msgstr "%s: lseek epäonnistui: %s"
-
-#: output.cc:3390 output.cc:3427
-#, c-format
-msgid "%s: write: %s"
-msgstr "%s: write epäonnistui: %s"
-
-#: output.cc:3398
+#: output.cc:4005
#, c-format
msgid "%s: mmap: %s"
msgstr "%s: mmap epäonnistui: %s"
-#: output.cc:3408
+#: output.cc:4085
+#, c-format
+msgid "%s: mmap: failed to allocate %lu bytes for output file: %s"
+msgstr "%s: mmap: epäonnistuttiin varaamaan %lu tavua tulostetiedostolle: %s"
+
+#: output.cc:4096
#, c-format
msgid "%s: munmap: %s"
msgstr "%s: munmap epäonnistui: %s"
-#: output.cc:3425
+#: output.cc:4115
#, c-format
msgid "%s: write: unexpected 0 return-value"
msgstr "%s: write: odottamaton 0-paluuarvo"
-#: output.cc:3439
+#: output.cc:4117
+#, c-format
+msgid "%s: write: %s"
+msgstr "%s: write epäonnistui: %s"
+
+#: output.cc:4132
#, c-format
msgid "%s: close: %s"
msgstr "%s: close epäonnistui: %s"
-#: output.h:415
+#: output.h:520
msgid "** section headers"
msgstr "** lohko-otsakkeet"
-#: output.h:451
+#: output.h:565
msgid "** segment headers"
msgstr "** segmenttiotsakkeet"
-#: output.h:490
+#: output.h:613
msgid "** file header"
msgstr "** tiedosto-otsake"
-#: output.h:696
+#: output.h:833
msgid "** fill"
msgstr "** täyte"
-#: output.h:850
+#: output.h:987
msgid "** string table"
msgstr "** merkkijonotaulu"
-#: output.h:1161
+#: output.h:1300
msgid "** dynamic relocs"
msgstr "** dynaamiset sijoitukset"
-#: output.h:1162 output.h:1498
+#: output.h:1301 output.h:1637
msgid "** relocs"
msgstr "** sijoitukset"
-#: output.h:1523
+#: output.h:1662
msgid "** group"
msgstr "** ryhmä"
-#: output.h:1630
+#: output.h:1774
msgid "** GOT"
msgstr "** GOT"
-#: output.h:1772
+#: output.h:1916
msgid "** dynamic"
msgstr "** dynaaminen"
-#: output.h:1890
+#: output.h:2039
msgid "** symtab xindex"
msgstr "** symtab xindex"
-#: parameters.cc:87
+#: parameters.cc:172
#, c-format
msgid "unrecognized output format %s"
msgstr "tunnistamaton tulostemuoto %s"
-#: powerpc.cc:1086 sparc.cc:1569 x86_64.cc:957
-msgid "requires unsupported dynamic reloc; recompile with -fPIC"
-msgstr "vaatii tukematonta dynaamista reloc-tietuetta, käännä uudelleen valitsimella -fPIC"
+#: plugin.cc:106
+#, c-format
+msgid "%s: could not load plugin library"
+msgstr "%s: ei voitu ladata lisäosakirjastoa"
+
+#: plugin.cc:116
+#, c-format
+msgid "%s: could not find onload entry point"
+msgstr "%s: ei kyetty löytämään sulkemistulokohtaa"
+
+#: plugin.cc:426
+msgid "Input files added by plug-ins in --incremental mode not supported yet.\n"
+msgstr "Lisäosien lisäämiä syötetiedostoja ei tueta vielä --incremental -tilassa.\n"
-#: powerpc.cc:1447 sparc.cc:2237 x86_64.cc:1561
+#: powerpc.cc:1502 sparc.cc:2307 x86_64.cc:1632
#, c-format
msgid "%s: unsupported REL reloc section"
msgstr "%s: tukematon REL-sijoituslohko"
-#: readsyms.cc:150
+#: readsyms.cc:191
#, c-format
msgid "%s: file is empty"
msgstr "%s: tiedosto on tyhjä"
#. Here we have to handle any other input file types we need.
-#: readsyms.cc:471
+#: readsyms.cc:575
#, c-format
msgid "%s: not an object or archive"
msgstr "%s: ei ole objekti tai arkisto"
-#: reduced_debug_output.cc:240
+#: reduced_debug_output.cc:236
msgid "Debug abbreviations extend beyond .debug_abbrev section; failed to reduce debug abbreviations"
msgstr "Vianjäljityslyhennykset laajenevat .debug_abbrev-lohkon ylitse; vianjäljityslyhenteiden vähentäminen epäonnistui"
-#: reduced_debug_output.cc:326
+#: reduced_debug_output.cc:322
msgid "Extremely large compile unit in debug info; failed to reduce debug info"
msgstr "Äärimmäisen laaja käännösyksikkö vianjäljitystiedoissa; vianjäljitystietojen vähentäminen epäonnistui"
-#: reduced_debug_output.cc:334
+#: reduced_debug_output.cc:330
msgid "Debug info extends beyond .debug_info section;failed to reduce debug info"
msgstr "Vianjäljitystiedot laajentuvat .debug_info-lohkon ylitse; vianjäljitystietojen vähentäminen epäonnistui"
-#: reduced_debug_output.cc:354 reduced_debug_output.cc:396
+#: reduced_debug_output.cc:350 reduced_debug_output.cc:392
msgid "Invalid DIE in debug info; failed to reduce debug info"
msgstr "Virheellinen DIE vianjäljitystiedoissa; vianjäljitystietojen vähentäminen epäonnistui"
-#: reduced_debug_output.cc:377
+#: reduced_debug_output.cc:373
msgid "Debug info extends beyond .debug_info section; failed to reduce debug info"
msgstr "Vianjäljitystiedot laajenevat .debug_info-lohkon ylitse; vianjäljitystietojen vähentäminen epäonnistui"
-#: reloc.cc:239 reloc.cc:743
+#: reloc.cc:297 reloc.cc:858
#, c-format
msgid "relocation section %u uses unexpected symbol table %u"
-msgstr "uudelleensijoituslohko %u käyttää odottomatonta symbolitaulua %u"
+msgstr "sijoituslohko %u käyttää odottomatonta symbolitaulua %u"
-#: reloc.cc:254 reloc.cc:761
+#: reloc.cc:312 reloc.cc:875
#, c-format
msgid "unexpected entsize for reloc section %u: %lu != %u"
msgstr "odottamaton entsize reloc-lohkolle %u: %lu != %u"
-#: reloc.cc:263 reloc.cc:770
+#: reloc.cc:321 reloc.cc:884
#, c-format
msgid "reloc section %u size %lu uneven"
msgstr "reloc-lohko %u koko %lu pariton"
-#: reloc.cc:992
+#: reloc.cc:1203
+#, c-format
+msgid "could not convert call to '%s' to '%s'"
+msgstr "ei voitu muuntaa kutsua kohteeseen ’%s’ kutsuksi kohteeseen ’%s’"
+
+#: reloc.cc:1343
#, c-format
msgid "reloc section size %zu is not a multiple of reloc size %d\n"
msgstr "reloc-lohkokoko %zu ei ole reloc-koon %d monikerta\n"
#. We should only see externally visible symbols in the symbol
#. table.
-#: resolve.cc:170
+#: resolve.cc:191
msgid "invalid STB_LOCAL symbol in external symbols"
msgstr "virheellinen STB_LOCAL-symboli ulkoisissa symboleissa"
#. Any target which wants to handle STB_LOOS, etc., needs to
#. define a resolve method.
-#: resolve.cc:176
+#: resolve.cc:197
msgid "unsupported symbol binding"
msgstr "tukematon symbolisidos"
-#. FIXME: Do a better job of reporting locations.
-#: resolve.cc:367
+#. A dynamic object cannot reference a hidden or internal symbol
+#. defined in another object.
+#: resolve.cc:266
#, c-format
-msgid "%s: multiple definition of %s"
-msgstr "%s: useita %s-määrittelyjä"
+msgid "%s symbol '%s' in %s is referenced by DSO %s"
+msgstr "%s symboli ’%s’ kohteessa %s on DSO %s:n viittaama"
-#: resolve.cc:368 resolve.cc:373
-msgid "command line"
-msgstr "komentorivi"
+#: resolve.cc:326
+#, c-format
+msgid "common of '%s' overriding smaller common"
+msgstr "’%s’-yhteissymboli korvaa pienemmän yhteissymbolin"
+
+#: resolve.cc:331
+#, c-format
+msgid "common of '%s' overidden by larger common"
+msgstr "’%s’-yhteissymboli korvattu laajemmalla yhteissymbolilla"
+
+#: resolve.cc:336
+#, c-format
+msgid "multiple common of '%s'"
+msgstr "useita ’%s’-yhteissymboleja."
+
+#: resolve.cc:442
+#, c-format
+msgid "multiple definition of '%s'"
+msgstr "useita ’%s’-määrittelyjä"
+
+#: resolve.cc:481
+#, c-format
+msgid "definition of '%s' overriding common"
+msgstr "’%s’-määrittely korvaa yhteissymbolin"
+
+#: resolve.cc:516
+#, c-format
+msgid "definition of '%s' overriding dynamic common definition"
+msgstr "’%s’-määrittely korvaa dynaamisen yhteismäärittelyn"
-#: resolve.cc:370
+#: resolve.cc:636
#, c-format
-msgid "%s: previous definition here"
-msgstr "%s: edellinen määrittely tässä"
+msgid "common '%s' overridden by previous definition"
+msgstr "yhteinen ’%s’ korvattu edellisellä määrittelyllä"
-#: script-sections.cc:432
+#: resolve.cc:766 resolve.cc:778
+msgid "command line"
+msgstr "komentorivi"
+
+#: script-sections.cc:690
msgid "dot may not move backward"
msgstr "piste ei voi siirtyä taaksepäin"
-#: script-sections.cc:498
+#: script-sections.cc:757
msgid "** expression"
msgstr "** lauseke"
-#: script-sections.cc:684
+#: script-sections.cc:941
msgid "fill value is not absolute"
msgstr "täytearvo ei ole absoluuttinen"
-#: script-sections.cc:1693
+#: script-sections.cc:1913
#, c-format
msgid "alignment of section %s is not absolute"
msgstr "lohkon %s tasaus ei ole absoluuttinen"
-#: script-sections.cc:1737
+#: script-sections.cc:1957
#, c-format
msgid "subalign of section %s is not absolute"
msgstr "lohkon %s alitasaus ei ole absoluuttinen"
-#: script-sections.cc:1752
+#: script-sections.cc:1972
#, c-format
msgid "fill of section %s is not absolute"
msgstr "lohkon %s täyte ei ole absoluuttinen"
-#: script-sections.cc:1828
+#: script-sections.cc:2048
msgid "SPECIAL constraints are not implemented"
msgstr "SPECIAL-rajoitteita ei ole toteutettu"
-#: script-sections.cc:1870
+#: script-sections.cc:2090
msgid "mismatched definition for constrained sections"
msgstr "täsmäämätön määrittely rajoitetuille lohkoille"
# DATA_SEGMENT_ALIGN on sisäänrakennettu funktio linkittäjän skriptikielessä.
-#: script-sections.cc:2395
+#: script-sections.cc:2634
msgid "DATA_SEGMENT_ALIGN may only appear once in a linker script"
msgstr "DATA_SEGMENT_ALIGN-funktio voi esiintyä vain kerran linkkeriskriptissä"
-#: script-sections.cc:2406
+#: script-sections.cc:2649
msgid "DATA_SEGMENT_RELRO_END may only appear once in a linker script"
msgstr "DATA_SEGMENT_RELRO_END-funktio voi esiintyä vain kerran linkkeriskriptissä"
-#: script-sections.cc:2411
+#: script-sections.cc:2654
msgid "DATA_SEGMENT_RELRO_END must follow DATA_SEGMENT_ALIGN"
msgstr "DATA_SEGMENT_RELRO_END-funktion on seurattava DATA_SEGMENT_ALIGN-funktiota"
-#: script-sections.cc:2570
+#: script-sections.cc:2826
msgid "no matching section constraint"
msgstr "ei täsmäävää lohkorajoitusta"
-#: script-sections.cc:2890
+#: script-sections.cc:3151
msgid "TLS sections are not adjacent"
msgstr "TLS-lohkot eivät ole vierekkäisiä"
-#: script-sections.cc:3016
+#: script-sections.cc:3280
msgid "allocated section not in any segment"
msgstr "varattu lohko ei ole missään segmentissä"
-#: script-sections.cc:3048
+#: script-sections.cc:3309
#, c-format
msgid "no segment %s"
msgstr "ei segmenttiä %s"
-#: script-sections.cc:3058
+#: script-sections.cc:3323
msgid "section in two PT_LOAD segments"
msgstr "lohko kahdessa PT_LOAD-segmentissä"
-#: script-sections.cc:3065
+#: script-sections.cc:3330
msgid "allocated section not in any PT_LOAD segment"
msgstr "varattu lohko ei ole missään PT_LOAD-segmentissä"
-#: script-sections.cc:3093
+#: script-sections.cc:3358
msgid "may only specify load address for PT_LOAD segment"
msgstr "voi vain antaa latausosoitteen PT_LOAD-segmentille"
-#: script-sections.cc:3117
+#: script-sections.cc:3382
#, c-format
msgid "PHDRS load address overrides section %s load address"
msgstr "PHDRS-komennon latausosoite korvaa lohkon %s latausosoitteen"
#. We could support this if we wanted to.
-#: script-sections.cc:3128
+#: script-sections.cc:3393
msgid "using only one of FILEHDR and PHDRS is not currently supported"
msgstr "vain yhden avainsanoista FILEHDR ja PHDRS käyttämistä ei nykyisin tueta"
-#: script-sections.cc:3143
+#: script-sections.cc:3408
msgid "sections loaded on first page without room for file and program headers are not supported"
msgstr "ei tueta ensimmäisellä sivulla ladattuja lohkoja ilman tilaa tiedostolle ja ohjelmaotsakkeille"
-#: script-sections.cc:3149
+#: script-sections.cc:3414
msgid "using FILEHDR and PHDRS on more than one PT_LOAD segment is not currently supported"
msgstr "avainsanojen FILEHDR ja PHDRS käyttämistä useammassa kuin yhdessä PT_LOAD-segmentissä ei nykyisin tueta"
-#: script.cc:1063
+#: script.cc:1072
msgid "invalid use of PROVIDE for dot symbol"
msgstr "virheellinen PROVIDE-käyttö dot-symbolille"
-#: script.cc:1065
-msgid "invalid assignment to dot outside of SECTIONS"
-msgstr "virheellinen arvonasetus dot-symbolille SECTIONS-lauseen ulkopuolella"
-
-#: script.cc:1995
+#: script.cc:2132
#, c-format
msgid "%s:%d:%d: %s"
msgstr "%s:%d:%d: %s"
#. There are some options that we could handle here--e.g.,
#. -lLIBRARY. Should we bother?
-#: script.cc:2143
+#: script.cc:2297
#, c-format
msgid "%s:%d:%d: ignoring command OPTION; OPTION is only valid for scripts specified via -T/--script"
msgstr "%s:%d:%d: ohitetaan komento OPTION; OPTION on kelvollinen vain skripteillä, jotka määritellään valitsimilla -T/--script"
-#: script.cc:2168
+#: script.cc:2362
#, c-format
msgid "%s:%d:%d: ignoring SEARCH_DIR; SEARCH_DIR is only valid for scripts specified via -T/--script"
msgstr "%s:%d:%d: ohitetaan SEARCH_DIR; SEARCH_DIR on kelvollinen vain skripteille, jotka on määritelty valitsimien -T/--script kautta"
-#: script.cc:2411 script.cc:2425
+#: script.cc:2606 script.cc:2620
#, c-format
msgid "%s:%d:%d: DATA_SEGMENT_ALIGN not in SECTIONS clause"
msgstr "%s:%d:%d: DATA_SEGMENT_ALIGN-funktio ei ole SECTIONS-lauseessa"
-#: script.cc:2543
+#: script.cc:2739
msgid "unknown PHDR type (try integer)"
msgstr "tuntematon PHDR-tyyppi (yritä kokonaislukua)"
# Esimerkiksi puhelinluettelossa A-kirjaimella alkavat nimet muodostavat yhden bucketin, B-kirjaimella alkavat toisen jne. A ja B ovat hash key -avaimia.
-#: stringpool.cc:526
+#: stringpool.cc:528
#, c-format
msgid "%s: %s entries: %zu; buckets: %zu\n"
msgstr "%s: %s alkiota: %zu; lohkot: %zu\n"
-#: stringpool.cc:530
+#: stringpool.cc:532
#, c-format
msgid "%s: %s entries: %zu\n"
msgstr "%s: %s alkiota: %zu\n"
-#: stringpool.cc:533
+#: stringpool.cc:535
#, c-format
msgid "%s: %s Stringdata structures: %zu\n"
msgstr "%s: %s Stringdata-rakenteet: %zu\n"
# ensimmäinen argumentti on objektinimi, toinen nimi
-#: symtab.cc:623
+#: symtab.cc:857
#, c-format
msgid "%s: reference to %s"
msgstr "%s: viite nimeen %s"
# ensimmäinen argumentti on objektinimi, toinen nimi
-#: symtab.cc:625
+#: symtab.cc:859
#, c-format
msgid "%s: definition of %s"
msgstr "%s: %s-määrittely"
-#: symtab.cc:860
+#: symtab.cc:1052
#, c-format
msgid "bad global symbol name offset %u at %zu"
msgstr "väärä yleissymbolinimisiirros %u osoitteessa %zu"
-#: symtab.cc:999
+#: symtab.cc:1278
msgid "--just-symbols does not make sense with a shared object"
msgstr "--just-symbols ei tunnu järkevältä jaetuille objekteille"
-#: symtab.cc:1005
+#: symtab.cc:1284
msgid "too few symbol versions"
msgstr "liian harvoja symboliversioita"
-#: symtab.cc:1054
+#: symtab.cc:1333
#, c-format
msgid "bad symbol name offset %u at %zu"
msgstr "väärä symbolinimisiirros %u osoitteessa %zu"
-#: symtab.cc:1117
+#: symtab.cc:1396
#, c-format
msgid "versym for symbol %zu out of range: %u"
msgstr "versym symbolille %zu lukualueen ulkopuolella: %u"
-#: symtab.cc:1125
+#: symtab.cc:1404
#, c-format
msgid "versym for symbol %zu has no name: %u"
msgstr "versym symbolille %zu ei ole nimeä: %u"
-#: symtab.cc:2035 symtab.cc:2251
+#: symtab.cc:2549 symtab.cc:2681
#, c-format
msgid "%s: unsupported symbol section 0x%x"
msgstr "%s: tukematon symbolilohko 0x%x"
-#: symtab.cc:2409
-#, c-format
-msgid "%s: undefined reference to '%s', version '%s'"
-msgstr "%s: määrittelemätön viite kohteeseen ’%s’, versio ’%s’"
-
-#: symtab.cc:2414
-#, c-format
-msgid "%s: undefined reference to '%s'"
-msgstr "%s: määrittelemätön viite kohteeseen ’%s’"
-
-#: symtab.cc:2498
+#: symtab.cc:2933
#, c-format
msgid "%s: symbol table entries: %zu; buckets: %zu\n"
msgstr "%s: symbolitaulualkiot: %zu; lohkot: %zu\n"
-#: symtab.cc:2501
+#: symtab.cc:2936
#, c-format
msgid "%s: symbol table entries: %zu\n"
msgstr "%s: symbolitaulutuloja: %zu\n"
-#: symtab.cc:2572
+#: symtab.cc:3007
#, c-format
msgid "while linking %s: symbol '%s' defined in multiple places (possible ODR violation):"
msgstr "kun linkitetään %s: symboli ’%s’ määritellään useissa paikoissa (mahdollinen ODR-ristiriita):"
-#: target-reloc.h:247
-msgid "Relocation refers to discarded comdat section"
-msgstr "Uudelleensijoitus viittaa hylättyyn comdat-lohkoon"
+#: target-reloc.h:259
+msgid "relocation refers to discarded comdat section"
+msgstr "sijoitus viittaa hylättyyn comdat-lohkoon"
-#: target-reloc.h:278
+#: target-reloc.h:298
#, c-format
msgid "reloc has bad offset %zu"
msgstr "reloc-tietueella on väärä siirros %zu"
+#: target.cc:90
+#, c-format
+msgid "%s: unsupported ELF file type %d"
+msgstr "%s: tukematon ELF-tiedostotyyppi %d"
+
+#: target.cc:157
+#, c-format
+msgid "linker does not include stack split support required by %s"
+msgstr "linkkeri ei sisällä kohteen %s vaatiman pinojakamisen tukea"
+
#: tls.h:59
msgid "TLS relocation out of range"
-msgstr "TLS-uudelleensijoitus lukualueen ulkopuolella"
+msgstr "TLS-sijoitus lukualueen ulkopuolella"
#: tls.h:73
msgid "TLS relocation against invalid instruction"
-msgstr "TLS-uudelleensijoitus virhellistä käskyä vastaan"
+msgstr "TLS-sijoitus virheellistä käskyä vastaan"
#. This output is intended to follow the GNU standards.
-#: version.cc:64
+#: version.cc:65
#, c-format
msgid "Copyright 2008 Free Software Foundation, Inc.\n"
msgstr "Copyright 2008 Free Software Foundation, Inc.\n"
-#: version.cc:65
+#: version.cc:66
#, c-format
msgid ""
"This program is free software; you may redistribute it under the terms of\n"
@@ -1868,24 +2246,39 @@ msgstr ""
msgid "%s failed: %s"
msgstr "%s epäonnistui: %s"
-#: x86_64.cc:2104
+#: x86_64.cc:2184
#, c-format
msgid "unsupported reloc type %u"
msgstr "tukematon reloc-tietuetyyppi %u"
-#: x86_64.cc:2441
+#: x86_64.cc:2524
#, c-format
msgid "unsupported reloc %u against local symbol"
msgstr "tukematon reloc %u -tietue paikallista symbolia vastaan"
-#~ msgid "Copyright 2009 Free Software Foundation, Inc.\n"
-#~ msgstr "Copyright 2009 Free Software Foundation, Inc.\n"
+#~ msgid " applied to section relative value"
+#~ msgstr " sovellettu lohkosuhteelliseen arvoon"
+
+#~ msgid "cannot find -l%s"
+#~ msgstr "ei voi löytää -l%s"
+
+#~ msgid "%s: ELF file too short"
+#~ msgstr "%s: ELF-tiedosto on liian lyhyt"
+
+#~ msgid "%s: invalid ELF version 0"
+#~ msgstr "%s: virheellinen ELF-versio 0"
+
+#~ msgid "%s: unsupported ELF version %d"
+#~ msgstr "%s: tukematon ELF-versio %d"
+
+#~ msgid "%s: invalid ELF class 0"
+#~ msgstr "%s: virheellinen ELF-luokka 0"
-#~ msgid "symbols %s %zu %zu\n"
-#~ msgstr "symbolit %s %zu %zu\n"
+#~ msgid "%s: unsupported ELF class %d"
+#~ msgstr "%s: tukematon ELF-luokka %d"
-#~ msgid "archive %s %zu %zu\n"
-#~ msgstr "arkisto %s %zu %zu\n"
+#~ msgid "%s: invalid ELF data encoding"
+#~ msgstr "%s: virheellinen ELF-datakoodaus"
-#~ msgid "Incremental linking might be possible (not implemented yet)\n"
-#~ msgstr "Kasvava linkitys saattaisi olla mahdollista (ei ole vielä toteutettu)\n"
+#~ msgid "%s: unsupported ELF data encoding %d"
+#~ msgstr "%s: tukematon ELF-datakoodaus %d"
diff --git a/binutils-2.22/gold/po/it.gmo b/binutils-2.22/gold/po/it.gmo
new file mode 100644
index 0000000..b79d83a
--- /dev/null
+++ b/binutils-2.22/gold/po/it.gmo
Binary files differ
diff --git a/binutils-2.22/gold/po/it.po b/binutils-2.22/gold/po/it.po
new file mode 100644
index 0000000..144a1e7
--- /dev/null
+++ b/binutils-2.22/gold/po/it.po
@@ -0,0 +1,2247 @@
+# Italian translation for gold.
+# Copyright (C) 2011 Free Software Foundation, Inc.
+# This file is distributed under the same license as the binutils package.
+# Sergio Zanchetta <primes2h@ubuntu.com>, 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: gold-2.21.53\n"
+"Report-Msgid-Bugs-To: bug-binutils@gnu.org\n"
+"POT-Creation-Date: 2010-03-03 15:08+0100\n"
+"PO-Revision-Date: 2011-11-14 18:30+0100\n"
+"Last-Translator: Sergio Zanchetta <primes2h@ubuntu.com>\n"
+"Language-Team: Italian <tp@lists.linux.it>\n"
+"Language: it\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural= (n != 1)\n"
+
+#: archive.cc:119
+#, c-format
+msgid "%s: no archive symbol table (run ranlib)"
+msgstr "%s: nessuna tabella dei simboli dell'archivio (eseguire ranlib)"
+
+#: archive.cc:204
+#, c-format
+msgid "%s: bad archive symbol table names"
+msgstr "%s: nomi delle tabelle dei simboli dell'archivio errati"
+
+#: archive.cc:236
+#, c-format
+msgid "%s: malformed archive header at %zu"
+msgstr "%s: intestazione malformata dell'archivio alla %zu"
+
+#: archive.cc:256
+#, c-format
+msgid "%s: malformed archive header size at %zu"
+msgstr "%s: dimensione malformata dell'intestazione dell'archivio alla %zu"
+
+#: archive.cc:267
+#, c-format
+msgid "%s: malformed archive header name at %zu"
+msgstr "%s: nome malformato dell'intestazione dell'archivio alla %zu"
+
+#: archive.cc:297
+#, c-format
+msgid "%s: bad extended name index at %zu"
+msgstr "%s: indice dei nomi estesi errato alla %zu"
+
+#: archive.cc:307
+#, c-format
+msgid "%s: bad extended name entry at header %zu"
+msgstr "%s: voce di nome esteso errata all'intestazione %zu"
+
+#: archive.cc:404
+#, c-format
+msgid "%s: short archive header at %zu"
+msgstr "%s: intestazione corta dell'archivio alla %zu"
+
+#: archive.cc:560
+#, c-format
+msgid "%s: member at %zu is not an ELF object"
+msgstr "%s: il membro alla %zu non è un oggetto ELF"
+
+#: archive.cc:879
+#, c-format
+msgid "%s: archive libraries: %u\n"
+msgstr "%s: librerie di archivio: %u\n"
+
+#: archive.cc:881
+#, c-format
+msgid "%s: total archive members: %u\n"
+msgstr "%s: membri totali dell'archivio: %u\n"
+
+#: archive.cc:883
+#, c-format
+msgid "%s: loaded archive members: %u\n"
+msgstr "%s: membri caricati dell'archivio: %u\n"
+
+#: arm.cc:1149 i386.cc:536 sparc.cc:1087 x86_64.cc:565
+msgid "** PLT"
+msgstr "** PLT"
+
+#: arm.cc:1364 i386.cc:880 powerpc.cc:1014 sparc.cc:1502 x86_64.cc:955
+#: x86_64.cc:1265
+#, c-format
+msgid "%s: unsupported reloc %u against local symbol"
+msgstr "%s: rilocazione %u non supportata contro un simbolo locale"
+
+#: arm.cc:1404 powerpc.cc:1105 sparc.cc:1592 x86_64.cc:992
+msgid "requires unsupported dynamic reloc; recompile with -fPIC"
+msgstr "richiede rilocazioni dinamiche non supportate; ricompilare con -fPIC"
+
+#. These are relocations which should only be seen by the
+#. dynamic linker, and should never be seen here.
+#: arm.cc:1519 arm.cc:1739 arm.cc:2354 i386.cc:1002 i386.cc:1334
+#: powerpc.cc:1223 powerpc.cc:1432 sparc.cc:1877 sparc.cc:2238 x86_64.cc:1145
+#: x86_64.cc:1453
+#, c-format
+msgid "%s: unexpected reloc %u in object file"
+msgstr "%s: rilocazione %u inattesa nel file oggetto"
+
+#: arm.cc:1538 i386.cc:1171 powerpc.cc:1242 sparc.cc:1896 x86_64.cc:1279
+#: x86_64.cc:1571
+#, c-format
+msgid "%s: unsupported reloc %u against global symbol %s"
+msgstr "%s: rilocazione %u non supportata contro il simbolo globale %s"
+
+#: arm.cc:1804 i386.cc:1542
+#, c-format
+msgid "%s: unsupported RELA reloc section"
+msgstr "%s: sezione di rilocazione RELA non supportata"
+
+#: arm.cc:2047
+msgid "relocation R_ARM_MOVW_ABS_NC cannot be used when makinga shared object; recompile with -fPIC"
+msgstr "impossibile usare la rilocazione R_ARM_MOVW_ABS_NC quando viene creato un oggetto condiviso; ricompilare con -fPIC"
+
+#: arm.cc:2056
+msgid "relocation R_ARM_MOVT_ABS cannot be used when makinga shared object; recompile with -fPIC"
+msgstr "impossibile usare la rilocazione R_ARM_MOVT_ABS quando viene creato un oggetto condiviso; ricompilare con -fPIC"
+
+#: arm.cc:2067
+msgid "relocation R_ARM_THM_MOVW_ABS_NC cannot be used whenmaking a shared object; recompile with -fPIC"
+msgstr "impossibile usare la rilocazione R_ARM_THM_MOVW_ABS_NC quando viene creato un oggetto condiviso; ricompilare con -fPIC"
+
+#: arm.cc:2077
+msgid "relocation R_ARM_THM_MOVT_ABS cannot be used whenmaking a shared object; recompile with -fPIC"
+msgstr "impossibile usare la rilocazione R_ARM_THM_MOVT_ABS quando viene creato un oggetto condiviso; ricompilare con -fPIC"
+
+#: arm.cc:2141
+msgid "cannot find origin of R_ARM_BASE_PREL"
+msgstr "impossibile trovare l'origine di R_ARM_BASE_PREL"
+
+#: arm.cc:2169
+msgid "cannot find origin of R_ARM_BASE_ABS"
+msgstr "impossibile trovare l'origine di R_ARM_BASE_ABS"
+
+#: arm.cc:2230 i386.cc:1820 i386.cc:2521 powerpc.cc:1798 sparc.cc:2711
+#: x86_64.cc:1935 x86_64.cc:2518
+#, c-format
+msgid "unexpected reloc %u in object file"
+msgstr "rilocazione %u inattesa nel file oggetto"
+
+#: arm.cc:2236 i386.cc:1852 i386.cc:1931 i386.cc:1983 i386.cc:2014
+#: i386.cc:2076 powerpc.cc:1804 sparc.cc:2717 sparc.cc:2900 sparc.cc:2961
+#: sparc.cc:3068 x86_64.cc:1956 x86_64.cc:2039 x86_64.cc:2094 x86_64.cc:2119
+#, c-format
+msgid "unsupported reloc %u"
+msgstr "rilocazione %u non supportata"
+
+#: arm.cc:2248
+#, c-format
+msgid "relocation overflow in relocation %u"
+msgstr "overflow nella rilocazione %u"
+
+#: arm.cc:2256
+#, c-format
+msgid "unexpected opcode while processing relocation %u"
+msgstr "opcode inatteso durante l'elaborazione della rilocazione %u"
+
+#: arm.cc:2359 i386.cc:2535
+#, c-format
+msgid "unsupported reloc %u in object file"
+msgstr "rilocazione %u non supportata nel file oggetto"
+
+#: binary.cc:129
+#, c-format
+msgid "cannot open %s: %s:"
+msgstr "impossibile aprire %s: %s:"
+
+#: compressed_output.cc:128
+msgid "not compressing section data: zlib error"
+msgstr "i dati di sezione non vengono compressi: errore di zlib"
+
+#: cref.cc:244
+#, c-format
+msgid "cannot open symbol count file %s: %s"
+msgstr "impossibile aprire il file %s di conteggio dei simboli: %s"
+
+#: descriptors.cc:116
+#, c-format
+msgid "file %s was removed during the link"
+msgstr "rimosso il file %s durante l'operazione di link"
+
+#: descriptors.cc:169
+msgid "out of file descriptors and couldn't close any"
+msgstr "descrittori di file terminati senza poterne chiudere alcuno"
+
+#: descriptors.cc:190 descriptors.cc:226
+#, c-format
+msgid "while closing %s: %s"
+msgstr "mentre viene chiuso %s: %s"
+
+#: dirsearch.cc:71
+#, c-format
+msgid "%s: can not read directory: %s"
+msgstr "%s: impossibile leggere la directory: %s"
+
+#: dwarf_reader.cc:53 dwarf_reader.cc:84
+msgid "Unusually large LEB128 decoded, debug information may be corrupted"
+msgstr "Decodificato un LEB128 insolitamente grande, le informazioni di debug potrebbero essere danneggiate"
+
+#: dynobj.cc:164
+#, c-format
+msgid "unexpected duplicate type %u section: %u, %u"
+msgstr "sezione duplicata di tipo %u inattesa: %u, %u"
+
+#: dynobj.cc:200
+#, c-format
+msgid "unexpected link in section %u header: %u != %u"
+msgstr "link inatteso nell'intestazione della sezione %u: %u != %u"
+
+#: dynobj.cc:236
+#, c-format
+msgid "DYNAMIC section %u link out of range: %u"
+msgstr "nella sezione DYNAMIC %u il link è fuori dall'intervallo: %u"
+
+#: dynobj.cc:244
+#, c-format
+msgid "DYNAMIC section %u link %u is not a strtab"
+msgstr "nella sezione DYNAMIC %u il link %u non è uno strtab"
+
+#: dynobj.cc:273
+#, c-format
+msgid "DT_SONAME value out of range: %lld >= %lld"
+msgstr "valore di DT_SONAME fuori dall'intervallo: %lld >= %lld"
+
+#: dynobj.cc:285
+#, c-format
+msgid "DT_NEEDED value out of range: %lld >= %lld"
+msgstr "valore di DT_NEEDED fuori dall'intervallo: %lld >= %lld"
+
+#: dynobj.cc:298
+msgid "missing DT_NULL in dynamic segment"
+msgstr "DT_NULL mancante nel segmento dinamico"
+
+#: dynobj.cc:344
+#, c-format
+msgid "invalid dynamic symbol table name index: %u"
+msgstr "indice dei nomi della tabella dei simboli dinamici non valido: %u"
+
+#: dynobj.cc:351
+#, c-format
+msgid "dynamic symbol table name section has wrong type: %u"
+msgstr "la sezione dei nomi della tabella dei simboli dinamici è di tipo errato: %u"
+
+#: dynobj.cc:438 object.cc:463 object.cc:1106
+#, c-format
+msgid "bad section name offset for section %u: %lu"
+msgstr "posizione del nome errata per la sezione %u: %lu"
+
+#: dynobj.cc:468
+#, c-format
+msgid "duplicate definition for version %u"
+msgstr "definizione duplicata per la versione %u"
+
+#: dynobj.cc:497
+#, c-format
+msgid "unexpected verdef version %u"
+msgstr "versione verdef %u inaspettata"
+
+#: dynobj.cc:513
+#, c-format
+msgid "verdef vd_cnt field too small: %u"
+msgstr "campo vd_cnt verdef troppo piccolo: %u"
+
+#: dynobj.cc:521
+#, c-format
+msgid "verdef vd_aux field out of range: %u"
+msgstr "campo vd_aux verdef fuori dall'intervallo: %u"
+
+#: dynobj.cc:532
+#, c-format
+msgid "verdaux vda_name field out of range: %u"
+msgstr "campo vda_name verdaux fuori dall'intervallo: %u"
+
+#: dynobj.cc:542
+#, c-format
+msgid "verdef vd_next field out of range: %u"
+msgstr "campo vd_next verdef fuori dall'intervallo: %u"
+
+#: dynobj.cc:576
+#, c-format
+msgid "unexpected verneed version %u"
+msgstr "versione verneed non attesa %u"
+
+#: dynobj.cc:585
+#, c-format
+msgid "verneed vn_aux field out of range: %u"
+msgstr "campo vn_aux verneed fuori dall'intervallo: %u"
+
+#: dynobj.cc:599
+#, c-format
+msgid "vernaux vna_name field out of range: %u"
+msgstr "campo vna_name vernaux fuori dall'intervallo: %u"
+
+#: dynobj.cc:610
+#, c-format
+msgid "verneed vna_next field out of range: %u"
+msgstr "campo vna_next verneed fuori dall'intervallo: %u"
+
+#: dynobj.cc:621
+#, c-format
+msgid "verneed vn_next field out of range: %u"
+msgstr "campo vn_next verneed fuori dall'intervallo: %u"
+
+#: dynobj.cc:670
+msgid "size of dynamic symbols is not multiple of symbol size"
+msgstr "la dimensione dei simboli dinamici non è un multiplo della dimensione del simbolo"
+
+#: dynobj.cc:1435
+#, c-format
+msgid "symbol %s has undefined version %s"
+msgstr "il simbolo %s non ha una versione %s definita"
+
+#: ehframe.h:82
+msgid "** eh_frame_hdr"
+msgstr "** eh_frame_hdr"
+
+#: ehframe.h:353
+msgid "** eh_frame"
+msgstr "** eh_frame"
+
+#: errors.cc:81
+#, c-format
+msgid "%s: fatal error: "
+msgstr "%s: errore fatale: "
+
+#: errors.cc:92
+#, c-format
+msgid "%s: error: "
+msgstr "%s: errore: "
+
+#: errors.cc:104
+#, c-format
+msgid "%s: warning: "
+msgstr "%s: attenzione: "
+
+#: errors.cc:128
+#, c-format
+msgid "%s: %s: error: "
+msgstr "%s: %s: errore: "
+
+#: errors.cc:144
+#, c-format
+msgid "%s: %s: warning: "
+msgstr "%s: %s: attenzione: "
+
+#: errors.cc:167
+#, c-format
+msgid "%s: %s: error: undefined reference to '%s'\n"
+msgstr "%s: %s: errore: riferimento non definito a \"%s\"\n"
+
+#: errors.cc:172
+#, c-format
+msgid "%s: %s: error: undefined reference to '%s', version '%s'\n"
+msgstr "%s: %s: errore: riferimento non definito a \"%s\", versione \"%s\"\n"
+
+#: errors.cc:182
+#, c-format
+msgid "%s: "
+msgstr "%s: "
+
+#: expression.cc:172
+#, c-format
+msgid "undefined symbol '%s' referenced in expression"
+msgstr "simbolo \"%s\" non definito referenziato nell'espressione"
+
+#: expression.cc:209
+msgid "invalid reference to dot symbol outside of SECTIONS clause"
+msgstr "riferimento non valido al simbolo dot fuori della direttiva SECTIONS"
+
+#. Handle unary operators. We use a preprocessor macro as a hack to
+#. capture the C operator.
+#: expression.cc:278
+msgid "unary "
+msgstr "unario "
+
+#. Handle binary operators. We use a preprocessor macro as a hack to
+#. capture the C operator. KEEP_LEFT means that if the left operand
+#. is section relative and the right operand is not, the result uses
+#. the same section as the left operand. KEEP_RIGHT is the same with
+#. left and right swapped. IS_DIV means that we need to give an error
+#. if the right operand is zero. WARN means that we should warn if
+#. used on section relative values in a relocatable link. We always
+#. warn if used on values in different sections in a relocatable link.
+#: expression.cc:400
+msgid "binary "
+msgstr "binario "
+
+#: expression.cc:404
+msgid " by zero"
+msgstr " per zero"
+
+#: expression.cc:575
+msgid "max applied to section relative value"
+msgstr "massimo calcolato su un valore relativo alla sezione"
+
+#: expression.cc:610
+msgid "min applied to section relative value"
+msgstr "minimo calcolato su un valore relativo alla sezione"
+
+#: expression.cc:740
+msgid "aligning to section relative value"
+msgstr "allineamento al valore relativo della sezione"
+
+#: expression.cc:895
+#, c-format
+msgid "unknown constant %s"
+msgstr "costante %s sconosciuta"
+
+#: expression.cc:1126
+msgid "SEGMENT_START not implemented"
+msgstr "SEGMENT_START non implementata"
+
+#: expression.cc:1135
+msgid "ORIGIN not implemented"
+msgstr "ORIGIN non implementata"
+
+#: expression.cc:1141
+msgid "LENGTH not implemented"
+msgstr "LENGTH non implementata"
+
+#: fileread.cc:65
+#, c-format
+msgid "munmap failed: %s"
+msgstr "munmap non riuscita: %s"
+
+#: fileread.cc:129
+#, c-format
+msgid "%s: fstat failed: %s"
+msgstr "%s: fstat non riuscita: %s"
+
+#: fileread.cc:169
+#, c-format
+msgid "could not reopen file %s"
+msgstr "impossibile riaprire il file %s"
+
+#: fileread.cc:302
+#, c-format
+msgid "%s: pread failed: %s"
+msgstr "%s: pread non riuscita: %s"
+
+#: fileread.cc:308
+#, c-format
+msgid "%s: file too short: read only %lld of %lld bytes at %lld"
+msgstr "%s: file troppo corto: letti solo %lld di %lld byte alla %lld"
+
+#: fileread.cc:372
+#, c-format
+msgid "%s: attempt to map %lld bytes at offset %lld exceeds size of file; the file may be corrupt"
+msgstr "%s: il tentativo di mappare %lld byte alla posizione %lld supera la dimensione del file, che potrebbe essere corrotto"
+
+#: fileread.cc:402
+#, c-format
+msgid "%s: mmap offset %lld size %lld failed: %s"
+msgstr "%s: mmap alla posizione %lld di dimensione %lld non riuscita: %s"
+
+#: fileread.cc:548
+#, c-format
+msgid "%s: lseek failed: %s"
+msgstr "%s: lseek non riuscita: %s"
+
+#: fileread.cc:554
+#, c-format
+msgid "%s: readv failed: %s"
+msgstr "%s: readv non riuscita: %s"
+
+#: fileread.cc:557
+#, c-format
+msgid "%s: file too short: read only %zd of %zd bytes at %lld"
+msgstr "%s: file troppo corto: letti solo %zd di %zd byte alla %lld"
+
+#: fileread.cc:706
+#, c-format
+msgid "%s: total bytes mapped for read: %llu\n"
+msgstr "%s: byte totali mappati per la lettura: %llu\n"
+
+#: fileread.cc:708
+#, c-format
+msgid "%s: maximum bytes mapped for read at one time: %llu\n"
+msgstr "%s: byte massimi mappati alla volta per la lettura: %llu\n"
+
+#: fileread.cc:791
+#, c-format
+msgid "%s: stat failed: %s"
+msgstr "%s: stat non riuscita: %s"
+
+#: fileread.cc:849
+#, c-format
+msgid "cannot find %s%s"
+msgstr "impossibile trovare %s%s"
+
+#: fileread.cc:880
+#, c-format
+msgid "cannot find %s"
+msgstr "impossibile trovare %s"
+
+#: fileread.cc:904
+#, c-format
+msgid "cannot open %s: %s"
+msgstr "impossibile aprire %s: %s"
+
+#: gold-threads.cc:103
+#, c-format
+msgid "pthead_mutextattr_init failed: %s"
+msgstr "pthead_mutextattr_init non riuscita: %s"
+
+#: gold-threads.cc:107
+#, c-format
+msgid "pthread_mutextattr_settype failed: %s"
+msgstr "pthread_mutextattr_settype non riuscita: %s"
+
+#: gold-threads.cc:112
+#, c-format
+msgid "pthread_mutex_init failed: %s"
+msgstr "pthread_mutex_init non riuscita: %s"
+
+#: gold-threads.cc:116
+#, c-format
+msgid "pthread_mutexattr_destroy failed: %s"
+msgstr "pthread_mutexattr_destroy non riuscita: %s"
+
+#: gold-threads.cc:123
+#, c-format
+msgid "pthread_mutex_destroy failed: %s"
+msgstr "pthread_mutex_destroy non riuscita: %s"
+
+#: gold-threads.cc:131 gold-threads.cc:382
+#, c-format
+msgid "pthread_mutex_lock failed: %s"
+msgstr "pthread_mutex_lock non riuscita: %s"
+
+#: gold-threads.cc:139 gold-threads.cc:394
+#, c-format
+msgid "pthread_mutex_unlock failed: %s"
+msgstr "pthread_mutex_unlock non riuscita: %s"
+
+#: gold-threads.cc:220
+#, c-format
+msgid "pthread_cond_init failed: %s"
+msgstr "pthread_cond_init non riuscita: %s"
+
+#: gold-threads.cc:227
+#, c-format
+msgid "pthread_cond_destroy failed: %s"
+msgstr "pthread_cond_destroy non riuscita: %s"
+
+#: gold-threads.cc:236
+#, c-format
+msgid "pthread_cond_wait failed: %s"
+msgstr "pthread_cond_wait non riuscita: %s"
+
+#: gold-threads.cc:244
+#, c-format
+msgid "pthread_cond_signal failed: %s"
+msgstr "pthread_cond_signal non riuscita: %s"
+
+#: gold-threads.cc:252
+#, c-format
+msgid "pthread_cond_broadcast failed: %s"
+msgstr "pthread_cond_broadcast non riuscita: %s"
+
+#: gold-threads.cc:388
+#, c-format
+msgid "pthread_once failed: %s"
+msgstr "pthread_once non riuscita: %s"
+
+#: gold.cc:91
+#, c-format
+msgid "%s: internal error in %s, at %s:%d\n"
+msgstr "%s: errore interno in %s, in %s:%d\n"
+
+#: gold.cc:173
+msgid "no input files"
+msgstr "nessun file di input"
+
+#: gold.cc:226
+msgid "cannot mix -r with --gc-sections or --icf"
+msgstr "impossibile usare -r con --gc-sections o --icf"
+
+#: gold.cc:407
+#, c-format
+msgid "cannot mix -static with dynamic object %s"
+msgstr "impossibile usare -static con l'oggetto dinamico %s"
+
+#: gold.cc:411
+#, c-format
+msgid "cannot mix -r with dynamic object %s"
+msgstr "impossibile usare -r con l'oggetto dinamico %s"
+
+#: gold.cc:415
+#, c-format
+msgid "cannot use non-ELF output format with dynamic object %s"
+msgstr "impossibile usare un formato di output non ELF con l'oggetto dinamico %s"
+
+#: gold.cc:427
+#, c-format
+msgid "cannot mix split-stack '%s' and non-split-stack '%s' when using -r"
+msgstr "impossibile usare insieme \"%s\" split-stack e \"%s\" non-split-stack con l'opzione -r"
+
+#. FIXME: This needs to specify the location somehow.
+#: i386.cc:232 i386.cc:1669 sparc.cc:234 sparc.cc:2395 x86_64.cc:237
+#: x86_64.cc:1732
+msgid "missing expected TLS relocation"
+msgstr "manca la rilocazione TLS attesa"
+
+#: i386.cc:944 x86_64.cc:1068
+#, c-format
+msgid "section symbol %u has bad shndx %u"
+msgstr "simbolo di sezione %u con shndx %u errato"
+
+#: i386.cc:1036 i386.cc:1060 sparc.cc:1777 x86_64.cc:1176 x86_64.cc:1204
+#, c-format
+msgid "local symbol %u has bad shndx %u"
+msgstr "simbolo locale %u con shndx %u errato"
+
+#: i386.cc:1991
+msgid "both SUN and GNU model TLS relocations"
+msgstr "rilocazioni TLS sia modello SUN che GNU"
+
+#: i386.cc:2730 x86_64.cc:2719
+#, c-format
+msgid "failed to match split-stack sequence at section %u offset %0zx"
+msgstr "impossibile far corrispondere la sequenza split-stack alla sezione %u con posizione %0zx"
+
+#: icf.cc:616
+#, c-format
+msgid "%s: ICF Converged after %u iteration(s)"
+msgstr "%s: convergenza di ICF dopo %u iterazione(i)"
+
+#: icf.cc:619
+#, c-format
+msgid "%s: ICF stopped after %u iteration(s)"
+msgstr "%s: arresto di ICF dopo %u iterazione(i)"
+
+#: icf.cc:633
+#, c-format
+msgid "Could not find symbol %s to unfold\n"
+msgstr "Impossibile trovare il simbolo %s da espandere\n"
+
+#: incremental.cc:242
+#, c-format
+msgid "the link might take longer: cannot perform incremental link: %s"
+msgstr "il link potrebbe durare più tempo: impossibile effettuare il link incrementale: %s"
+
+#: incremental.cc:302
+msgid "no incremental data from previous build"
+msgstr "nessun dato incrementale dalla creazione precedente"
+
+#: incremental.cc:309 incremental.cc:332
+msgid "invalid incremental build data"
+msgstr "dati di creazione incrementale non validi"
+
+#: incremental.cc:321
+msgid "different version of incremental build data"
+msgstr "versione diversa dei dati di creazione incrementale"
+
+#: incremental.cc:338
+msgid "command line changed"
+msgstr "la riga di comando è cambiata"
+
+#: incremental.cc:362
+#, c-format
+msgid "unsupported ELF machine number %d"
+msgstr "numero di macchina ELF %d non supportata"
+
+#: incremental.cc:387
+msgid "output is not an ELF file."
+msgstr "l'output non è un file ELF."
+
+#: incremental.cc:410
+msgid "unsupported file: 32-bit, big-endian"
+msgstr "file non supportato: 32 bit, big-endian"
+
+#: incremental.cc:419
+msgid "unsupported file: 32-bit, little-endian"
+msgstr "file non supportato: 32 bit, little-endian"
+
+#: incremental.cc:431
+msgid "unsupported file: 64-bit, big-endian"
+msgstr "file non supportato: 64 bit, big-endian"
+
+#: incremental.cc:440
+msgid "unsupported file: 64-bit, little-endian"
+msgstr "file non supportato: 64 bit, little-endian"
+
+#: layout.cc:1887
+#, c-format
+msgid "--build-id=uuid failed: could not open /dev/urandom: %s"
+msgstr "--build-id=uuid non riuscita: impossibile aprire /dev/urandom: %s"
+
+#: layout.cc:1894
+#, c-format
+msgid "/dev/urandom: read failed: %s"
+msgstr "/dev/urandom: lettura non riuscita: %s"
+
+#: layout.cc:1896
+#, c-format
+msgid "/dev/urandom: expected %zu bytes, got %zd bytes"
+msgstr "/dev/urandom: attesi %zu byte, ottenuti %zd byte"
+
+#: layout.cc:1918
+#, c-format
+msgid "--build-id argument '%s' not a valid hex number"
+msgstr "l'argomento \"%s\" di --build-id non è un numero esadecimale valido"
+
+#: layout.cc:1924
+#, c-format
+msgid "unrecognized --build-id argument '%s'"
+msgstr "argomento \"%s\" di --build-id non riconosciuto"
+
+#: layout.cc:2337
+#, c-format
+msgid "load segment overlap [0x%llx -> 0x%llx] and [0x%llx -> 0x%llx]"
+msgstr "sovrapposizione del segmento di caricamento [0x%llx -> 0x%llx] e [0x%llx -> 0x%llx]"
+
+#: mapfile.cc:70
+#, c-format
+msgid "cannot open map file %s: %s"
+msgstr "impossibile aprire il file di mappa %s: %s"
+
+#: mapfile.cc:84
+#, c-format
+msgid "cannot close map file: %s"
+msgstr "impossibile chiudere il file di mappa: %s"
+
+#: mapfile.cc:116
+#, c-format
+msgid ""
+"Archive member included because of file (symbol)\n"
+"\n"
+msgstr ""
+"Incluso membro dell'archivio a causa del file (simbolo)\n"
+"\n"
+
+#: mapfile.cc:159
+#, c-format
+msgid ""
+"\n"
+"Allocating common symbols\n"
+msgstr ""
+"\n"
+"Allocazione dei simboli comuni\n"
+
+#: mapfile.cc:161
+#, c-format
+msgid ""
+"Common symbol size file\n"
+"\n"
+msgstr ""
+"Simbolo comune dimensione file\n"
+"\n"
+
+#: mapfile.cc:195
+#, c-format
+msgid ""
+"\n"
+"Memory map\n"
+"\n"
+msgstr ""
+"\n"
+"Mappa della memoria\n"
+"\n"
+
+#: mapfile.cc:361
+#, c-format
+msgid ""
+"\n"
+"Discarded input sections\n"
+"\n"
+msgstr ""
+"\n"
+"Sezioni di input scartate\n"
+"\n"
+
+#: merge.cc:455
+#, c-format
+msgid "%s: %s merged constants size: %lu; input: %zu; output: %zu\n"
+msgstr "%s: %s costanti unite, dimensione: %lu; input: %zu; output: %zu\n"
+
+#: merge.cc:478
+msgid "mergeable string section length not multiple of character size"
+msgstr "la lunghezza della sezione delle stringhe unibili non è un multiplo della dimensione carattere"
+
+#: merge.cc:494
+#, c-format
+msgid "%s: last entry in mergeable string section '%s' not null terminated"
+msgstr "%s: l'ultima voce nella sezione \"%s\" delle stringhe unibili non termina con un null"
+
+#: merge.cc:613
+#, c-format
+msgid "%s: %s input: %zu\n"
+msgstr "%s: %s input: %zu\n"
+
+#: merge.h:300
+msgid "** merge constants"
+msgstr "** unione delle costanti"
+
+#: merge.h:422
+msgid "** merge strings"
+msgstr "** unione delle stringhe"
+
+#: object.cc:75
+msgid "missing SHT_SYMTAB_SHNDX section"
+msgstr "sezione SHT_SYMTAB_SHNDX mancante"
+
+#: object.cc:119
+#, c-format
+msgid "symbol %u out of range for SHT_SYMTAB_SHNDX section"
+msgstr "simbolo %u fuori dall'intervallo per la sezione SHT_SYMTAB_SHNDX"
+
+#: object.cc:126
+#, c-format
+msgid "extended index for symbol %u out of range: %u"
+msgstr "indice esteso per il simbolo %u fuori dall'intervallo: %u"
+
+#: object.cc:148 object.cc:2331 output.cc:4052
+#, c-format
+msgid "%s: %s"
+msgstr "%s: %s"
+
+#: object.cc:190
+#, c-format
+msgid "section name section has wrong type: %u"
+msgstr "la sezione dei nomi di sezione è di tipo errato: %u"
+
+#: object.cc:546
+#, c-format
+msgid "invalid symbol table name index: %u"
+msgstr "indice dei nomi della tabella dei simboli non valido: %u"
+
+#: object.cc:552
+#, c-format
+msgid "symbol table name section has wrong type: %u"
+msgstr "la sezione dei nomi delle tabelle dei simboli è di tipo errato: %u"
+
+#: object.cc:641
+#, c-format
+msgid "section group %u info %u out of range"
+msgstr "gruppo di sezione %u con informazioni %u fuori dall'intervallo"
+
+#: object.cc:660
+#, c-format
+msgid "symbol %u name offset %u out of range"
+msgstr "simbolo %u con posizione del nome %u fuori dall'intervallo"
+
+#: object.cc:678
+#, c-format
+msgid "symbol %u invalid section index %u"
+msgstr "simbolo %u con indice di sezione non valido %u"
+
+#: object.cc:723
+#, c-format
+msgid "section %u in section group %u out of range"
+msgstr "sezione %u nel gruppo di sezione %u fuori dell'intervallo"
+
+#: object.cc:731
+#, c-format
+msgid "invalid section group %u refers to earlier section %u"
+msgstr "il gruppo di sezione non valido %u fa riferimento alla sezione precedente %u"
+
+#: object.cc:1037 reloc.cc:271 reloc.cc:838
+#, c-format
+msgid "relocation section %u has bad info %u"
+msgstr "la sezione di rilocazione %u ha informazioni %u errate"
+
+#: object.cc:1231
+#, c-format
+msgid "%s: removing unused section from '%s' in file '%s'"
+msgstr "%s: rimozione da \"%s\" della sezione inutilizzata nel file \"%s\""
+
+#: object.cc:1257
+#, c-format
+msgid "%s: ICF folding section '%s' in file '%s'into '%s' in file '%s'"
+msgstr "%s: ripiegamento ICF della sezione \"%s\" nel file \"%s\" dentro a \"%s\" nel file \"%s\""
+
+#: object.cc:1454
+msgid "size of symbols is not multiple of symbol size"
+msgstr "la dimensione dei simboli non è un multiplo di quella del simbolo"
+
+#: object.cc:1563
+#, c-format
+msgid "local symbol %u section name out of range: %u >= %u"
+msgstr "il simbolo locale %u ha il nome di sezione fuori dall'intervallo: %u >= %u"
+
+#: object.cc:1652
+#, c-format
+msgid "unknown section index %u for local symbol %u"
+msgstr "indice della sezione %u sconosciuto per il simbolo locale %u"
+
+#: object.cc:1661
+#, c-format
+msgid "local symbol %u section index %u out of range"
+msgstr "il simbolo locale %u ha l'indice di sezione %u fuori dall'intervallo"
+
+#: object.cc:2169
+#, c-format
+msgid "%s is not supported but is required for %s in %s"
+msgstr "%s non è supportato ma è richiesto per %s in %s"
+
+#: object.cc:2273
+#, c-format
+msgid "%s: unsupported ELF machine number %d"
+msgstr "%s: numero di macchina ELF %d non supportato"
+
+#: object.cc:2283
+#, c-format
+msgid "%s: incompatible target"
+msgstr "%s: obiettivo incompatibile"
+
+#: object.cc:2347 plugin.cc:1019
+#, c-format
+msgid "%s: not configured to support 32-bit big-endian object"
+msgstr "%s: non configurato per supportare gli oggetti a 32 bit big-endian"
+
+#: object.cc:2363 plugin.cc:1028
+#, c-format
+msgid "%s: not configured to support 32-bit little-endian object"
+msgstr "%s: non configurato per supportare gli oggetti a 32 bit little-endian"
+
+#: object.cc:2382 plugin.cc:1040
+#, c-format
+msgid "%s: not configured to support 64-bit big-endian object"
+msgstr "%s: non configurato per supportare gli oggetti a 64 bit big-endian"
+
+#: object.cc:2398 plugin.cc:1049
+#, c-format
+msgid "%s: not configured to support 64-bit little-endian object"
+msgstr "%s: non configurato per supportare gli oggetti a 64 bit little-endian"
+
+#: options.cc:156
+#, c-format
+msgid ""
+"Usage: %s [options] file...\n"
+"Options:\n"
+msgstr ""
+"Uso: %s [opzioni] file...\n"
+"Opzioni:\n"
+
+#. config.guess and libtool.m4 look in ld --help output for the
+#. string "supported targets".
+#: options.cc:164
+#, c-format
+msgid "%s: supported targets:"
+msgstr "%s: obiettivi supportati:"
+
+#: options.cc:176
+#, c-format
+msgid "Report bugs to %s\n"
+msgstr "Segnalare i bug su %s\n"
+
+#: options.cc:193 options.cc:203 options.cc:213
+#, c-format
+msgid "%s: invalid option value (expected an integer): %s"
+msgstr "%s: valore dell'opzione non valido (atteso un intero): %s"
+
+#: options.cc:223
+#, c-format
+msgid "%s: invalid option value (expected a floating point number): %s"
+msgstr "%s: valore dell'opzione non valido (atteso un numero in virgola mobile): %s"
+
+#: options.cc:232
+#, c-format
+msgid "%s: must take a non-empty argument"
+msgstr "%s: necessita di un argomento non vuoto"
+
+#: options.cc:273
+#, c-format
+msgid "%s: must take one of the following arguments: %s"
+msgstr "%s: necessita di uno tra i seguenti argomenti: %s"
+
+#: options.cc:300
+#, c-format
+msgid " Supported targets:\n"
+msgstr " Obiettivi supportati:\n"
+
+#: options.cc:409
+#, c-format
+msgid "unable to parse script file %s"
+msgstr "impossibile analizzare lo script %s"
+
+#: options.cc:417
+#, c-format
+msgid "unable to parse version script file %s"
+msgstr "impossibile analizzare lo script di versione %s"
+
+#: options.cc:425
+#, c-format
+msgid "unable to parse dynamic-list script file %s"
+msgstr "impossibile analizzare lo script dell'elenco dinamico %s"
+
+#: options.cc:522
+#, c-format
+msgid "format '%s' not supported; treating as elf (supported formats: elf, binary)"
+msgstr "formato \"%s\" non supportato; viene trattato come elf (formati supportati: elf, binario)"
+
+#: options.cc:538
+#, c-format
+msgid "%s: use the --help option for usage information\n"
+msgstr "%s: usare l'opzione --help per le informazioni sull'uso\n"
+
+#: options.cc:547
+#, c-format
+msgid "%s: %s: %s\n"
+msgstr "%s: %s: %s\n"
+
+#: options.cc:651
+msgid "unexpected argument"
+msgstr "argomento inatteso"
+
+#: options.cc:664 options.cc:725
+msgid "missing argument"
+msgstr "argomento mancante"
+
+#: options.cc:736
+msgid "unknown -z option"
+msgstr "opzione -z sconosciuta"
+
+#: options.cc:935
+#, c-format
+msgid "ignoring --threads: %s was compiled without thread support"
+msgstr "ignorata l'opzione --threads: %s compilato senza supporto per il threading"
+
+#: options.cc:942
+#, c-format
+msgid "ignoring --thread-count: %s was compiled without thread support"
+msgstr "ignorata l'opzione --thread-count: %s compilato senza supporto per il threading"
+
+#: options.cc:981
+#, c-format
+msgid "unable to open -retain-symbols-file file %s: %s"
+msgstr "impossibile aprire il file -retain-symbols-file %s: %s"
+
+#: options.cc:1003
+msgid "-shared and -static are incompatible"
+msgstr "-shared e -static sono incompatibili"
+
+#: options.cc:1005
+msgid "-shared and -pie are incompatible"
+msgstr "-shared e -pie sono incompatibili"
+
+#: options.cc:1008
+msgid "-shared and -r are incompatible"
+msgstr "-shared e -r sono incompatibili"
+
+#: options.cc:1010
+msgid "-pie and -r are incompatible"
+msgstr "-pie e -r sono incompatibili"
+
+#: options.cc:1014
+msgid "-retain-symbols-file does not yet work with -r"
+msgstr "-retain-symbols-file non può ancora essere usato con -r"
+
+#: options.cc:1020
+msgid "binary output format not compatible with -shared or -pie or -r"
+msgstr "il formato di output binario non è compatibile con -shared, -pie o -r"
+
+#: options.cc:1026
+#, c-format
+msgid "--hash-bucket-empty-fraction value %g out of range [0.0, 1.0)"
+msgstr "valore %g di --hash-bucket-empty-fraction fuori dall'intervallo [0.0, 1.0)"
+
+#: options.cc:1031
+msgid "Options --incremental-changed, --incremental-unchanged, --incremental-unknown require the use of --incremental"
+msgstr "Le opzioni --incremental-changed, --incremental-unchanged, --incremental-unknown richiedono l'uso di --incremental"
+
+#: options.cc:1097
+msgid "May not nest groups"
+msgstr "Non può nidificare i gruppi"
+
+#: options.cc:1109
+msgid "Group end without group start"
+msgstr "Il gruppo termina senza essere iniziato"
+
+#. I guess it's neither a long option nor a short option.
+#: options.cc:1174
+msgid "unknown option"
+msgstr "opzione sconosciuta"
+
+#: options.cc:1201
+#, c-format
+msgid "%s: missing group end\n"
+msgstr "%s: manca la fine del gruppo\n"
+
+#: options.h:571
+msgid "Report usage information"
+msgstr "Mostra le informazioni sull'uso"
+
+#: options.h:573
+msgid "Report version information"
+msgstr "Mostra le informazioni sulla versione"
+
+#: options.h:575
+msgid "Report version and target information"
+msgstr "Mostra la versione e le informazioni sugli obiettivi"
+
+#: options.h:584 options.h:635
+msgid "Not supported"
+msgstr "Non supportata"
+
+#: options.h:585 options.h:636
+msgid "Do not copy DT_NEEDED tags from shared libraries"
+msgstr "Non copia i tag DT_NEEDED dalle librerie condivise"
+
+#: options.h:588
+msgid "Allow unresolved references in shared libraries"
+msgstr "Ammette riferimenti non risolti nelle librerie condivise"
+
+#: options.h:589
+msgid "Do not allow unresolved references in shared libraries"
+msgstr "Non ammette riferimenti non risolti nelle librerie condivise"
+
+#: options.h:592
+msgid "Only set DT_NEEDED for shared libraries if used"
+msgstr "Imposta DT_NEEDED per le librerie condivise solo se usate"
+
+#: options.h:593
+msgid "Always DT_NEEDED for shared libraries"
+msgstr "Imposta sempre DT_NEEDED per le librerie condivise"
+
+#: options.h:600
+msgid "Set input format"
+msgstr "Imposta il formato di input"
+
+#: options.h:603
+msgid "-l searches for shared libraries"
+msgstr "-l cerca le librerie condivise"
+
+#: options.h:605
+msgid "-l does not search for shared libraries"
+msgstr "-l non cerca le librerie condivise"
+
+#: options.h:609
+msgid "Bind defined symbols locally"
+msgstr "Associa localmente i simboli definiti"
+
+#: options.h:612
+msgid "Bind defined function symbols locally"
+msgstr "Associa localmente i simboli definiti delle funzioni"
+
+#: options.h:615
+msgid "Generate build ID note"
+msgstr "Genera la nota ID di creazione"
+
+#: options.h:616 options.h:655
+msgid "[=STYLE]"
+msgstr "[=STILE]"
+
+#: options.h:619
+msgid "Check segment addresses for overlaps (default)"
+msgstr "Controlla le sovrapposizioni di segmenti negli indirizzi (predefinito)"
+
+#: options.h:620
+msgid "Do not check segment addresses for overlaps"
+msgstr "Non controlla le sovrapposizioni di segmenti negli indirizzi"
+
+#: options.h:624 options.h:629
+msgid "Compress .debug_* sections in the output file"
+msgstr "Comprime le sezioni .debug_* nel file di output"
+
+#: options.h:630
+msgid "[none]"
+msgstr "[nessuna]"
+
+#: options.h:639
+msgid "Define common symbols"
+msgstr "Definisce i simboli comuni"
+
+#: options.h:640
+msgid "Do not define common symbols"
+msgstr "Non definisce i simboli comuni"
+
+#: options.h:642 options.h:644
+msgid "Alias for -d"
+msgstr "Sinonimo per -d"
+
+#: options.h:647
+msgid "Turn on debugging"
+msgstr "Abilita il debug"
+
+#: options.h:648
+msgid "[all,files,script,task][,...]"
+msgstr "[all,files,script,task][,...]"
+
+#: options.h:651
+msgid "Define a symbol"
+msgstr "Definisce un simbolo"
+
+#: options.h:651
+msgid "SYMBOL=EXPRESSION"
+msgstr "SIMBOLO=ESPRESSIONE"
+
+#: options.h:654
+msgid "Demangle C++ symbols in log messages"
+msgstr "Decodifica i simboli C++ nei messaggi di log"
+
+#: options.h:658
+msgid "Do not demangle C++ symbols in log messages"
+msgstr "Non decodifica i simboli C++ nei messaggi di log"
+
+#: options.h:662
+msgid "Try to detect violations of the One Definition Rule"
+msgstr "Prova a rilevare violazioni alla regola della definizione unica (ODR)"
+
+#: options.h:666
+msgid "Delete all temporary local symbols"
+msgstr "Elimina tutti i simboli locali temporanei"
+
+#: options.h:669
+msgid "Add data symbols to dynamic symbols"
+msgstr "Aggiunge i simboli di dati ai simboli dinamici"
+
+#: options.h:672
+msgid "Add C++ operator new/delete to dynamic symbols"
+msgstr "Aggiunge l'operatore C++ new/delete ai simboli dinamici"
+
+#: options.h:675
+msgid "Add C++ typeinfo to dynamic symbols"
+msgstr "Aggiunge la classe C++ typeinfo ai simboli dinamici"
+
+#: options.h:678
+msgid "Read a list of dynamic symbols"
+msgstr "Legge un elenco di simboli dinamici"
+
+#: options.h:678 options.h:732 options.h:766 options.h:893 options.h:921
+msgid "FILE"
+msgstr "FILE"
+
+#: options.h:681
+msgid "Set program start address"
+msgstr "Imposta l'indirizzo di partenza del programma"
+
+#: options.h:681 options.h:908 options.h:910 options.h:912
+msgid "ADDRESS"
+msgstr "INDIRIZZO"
+
+#: options.h:684
+msgid "Exclude libraries from automatic export"
+msgstr "Esclude le librerie dall'esportazione automatica"
+
+#: options.h:688
+msgid "Export all dynamic symbols"
+msgstr "Esporta tutti i simboli dinamici"
+
+#: options.h:689
+msgid "Do not export all dynamic symbols (default)"
+msgstr "Non esporta tutti i simboli dinamici (predefinito)"
+
+#: options.h:692
+msgid "Create exception frame header"
+msgstr "Crea l'intestazione del frame di eccezione"
+
+#: options.h:695
+msgid "Treat warnings as errors"
+msgstr "Considera gli avvertimenti come errori"
+
+#: options.h:696
+msgid "Do not treat warnings as errors"
+msgstr "Non considera gli avvertimenti come errori"
+
+#: options.h:699
+msgid "Call SYMBOL at unload-time"
+msgstr "Chiama il SIMBOLO quando viene eseguito l'unload"
+
+#: options.h:699 options.h:729 options.h:873 options.h:915 options.h:936
+#: options.h:939
+msgid "SYMBOL"
+msgstr "SIMBOLO"
+
+#: options.h:702
+msgid "Set shared library name"
+msgstr "Imposta il nome della libreria condivisa"
+
+#: options.h:702 options.h:792
+msgid "FILENAME"
+msgstr "NOMEFILE"
+
+#: options.h:705
+msgid "Min fraction of empty buckets in dynamic hash"
+msgstr "Frazione minima di bucket vuoti nell'hash dinamico"
+
+#: options.h:706
+msgid "FRACTION"
+msgstr "FRAZIONE"
+
+#: options.h:709
+msgid "Dynamic hash style"
+msgstr "Stile dell'hash dinamico"
+
+#: options.h:709
+msgid "[sysv,gnu,both]"
+msgstr "[sysv,gnu,both]"
+
+#: options.h:713
+msgid "Set dynamic linker path"
+msgstr "Imposta il percorso del linker dinamico"
+
+#: options.h:713
+msgid "PROGRAM"
+msgstr "PROGRAMMA"
+
+#: options.h:716
+msgid "Work in progress; do not use"
+msgstr "Lavori in corso; non usare"
+
+#: options.h:717
+msgid "Do a full build"
+msgstr "Esegue una creazione completa"
+
+#: options.h:720
+msgid "Assume files changed"
+msgstr "Assume i file come modificati"
+
+#: options.h:723
+msgid "Assume files didn't change"
+msgstr "Assume i file come non modificati"
+
+#: options.h:726
+msgid "Use timestamps to check files (default)"
+msgstr "Effettua un controllo temporale sui file (predefinito)"
+
+#: options.h:729
+msgid "Call SYMBOL at load-time"
+msgstr "Chiama il SIMBOLO quando viene eseguito il load"
+
+#: options.h:732
+msgid "Read only symbol values from FILE"
+msgstr "Legge solo i valori dei simboli dal FILE"
+
+#: options.h:735
+msgid "Search for library LIBNAME"
+msgstr "Cerca la libreria NOMELIB"
+
+#: options.h:735
+msgid "LIBNAME"
+msgstr "NOMELIB"
+
+#: options.h:738
+msgid "Add directory to search path"
+msgstr "Aggiunge la directory al percorso di ricerca"
+
+#: options.h:738 options.h:813 options.h:816 options.h:820 options.h:887
+msgid "DIR"
+msgstr "DIR"
+
+#: options.h:741
+msgid "Ignored for compatibility"
+msgstr "Ignorato per compatibilità"
+
+#: options.h:741
+msgid "EMULATION"
+msgstr "EMULAZIONE"
+
+#: options.h:744
+msgid "Write map file on standard output"
+msgstr "Scrive il file di mappa sullo standard output"
+
+#: options.h:745
+msgid "Write map file"
+msgstr "Scrive il file di mappa"
+
+#: options.h:746
+msgid "MAPFILENAME"
+msgstr "NOMEFILEMAPPA"
+
+#: options.h:749
+msgid "Do not page align data"
+msgstr "Non allinea i dati alla pagina"
+
+#: options.h:751
+msgid "Do not page align data, do not make text readonly"
+msgstr "Non allinea i dati alla pagina, non imposta il testo in sola lettura"
+
+#: options.h:752
+msgid "Page align data, make text readonly"
+msgstr "Allinea i dati alla pagina, imposta il testo in sola lettura"
+
+#: options.h:755
+msgid "Enable use of DT_RUNPATH and DT_FLAGS"
+msgstr "Abilita l'uso di DT_RUNPATH e DT_FLAGS"
+
+#: options.h:756
+msgid "Disable use of DT_RUNPATH and DT_FLAGS"
+msgstr "Disabilita l'uso di DT_RUNPATH e DT_FLAGS"
+
+#: options.h:759
+msgid "Create an output file even if errors occur"
+msgstr "Crea un file di output anche in presenza di errori"
+
+#: options.h:762 options.h:958
+msgid "Report undefined symbols (even with --shared)"
+msgstr "Segnala i simboli indefiniti (anche con --shared)"
+
+#: options.h:766
+msgid "Set output file name"
+msgstr "Imposta il nome del file di output"
+
+#: options.h:769
+msgid "Optimize output file size"
+msgstr "Ottimizza la dimensione del file di output"
+
+#: options.h:769
+msgid "LEVEL"
+msgstr "LIVELLO"
+
+#: options.h:772
+msgid "Set output format"
+msgstr "Imposta il formato di output"
+
+#: options.h:772
+msgid "[binary]"
+msgstr "[binario]"
+
+#: options.h:775 options.h:777
+msgid "Create a position independent executable"
+msgstr "Crea un eseguibile indipendente dalla posizione"
+
+#: options.h:782
+msgid "Load a plugin library"
+msgstr "Carica una libreria di plugin"
+
+#: options.h:782
+msgid "PLUGIN"
+msgstr "PLUGIN"
+
+#: options.h:784
+msgid "Pass an option to the plugin"
+msgstr "Passa un'opzione al plugin"
+
+#: options.h:784
+msgid "OPTION"
+msgstr "OPZIONE"
+
+#: options.h:788
+msgid "Preread archive symbols when multi-threaded"
+msgstr "Esegue una pre-lettura dei simboli di archivio in caso di multi-threading"
+
+#: options.h:791
+msgid "Print symbols defined and used for each input"
+msgstr "Stampa i simboli definiti e usati per ogni input"
+
+#: options.h:795
+msgid "Ignored for SVR4 compatibility"
+msgstr "Ignorato per compatibilità con SVR4"
+
+#: options.h:798
+msgid "Generate relocations in output"
+msgstr "Genera le rilocazioni in output"
+
+#: options.h:801
+msgid "Generate relocatable output"
+msgstr "Genera output rilocabili"
+
+#: options.h:804
+msgid "Relax branches on certain targets"
+msgstr "Rilassa i rami su certi obiettivi"
+
+#: options.h:807
+msgid "keep only symbols listed in this file"
+msgstr "tiene solo i simboli elencati in questo file"
+
+#: options.h:807
+msgid "[file]"
+msgstr "[file]"
+
+#: options.h:813 options.h:816
+msgid "Add DIR to runtime search path"
+msgstr "Aggiunge DIR al percorso di ricerca in esecuzione"
+
+#: options.h:819
+msgid "Add DIR to link time shared library search path"
+msgstr "Aggiunge DIR al percorso di ricerca delle librerie condivise necessarie al linker"
+
+#: options.h:823
+msgid "Strip all symbols"
+msgstr "Elimina tutti i simboli"
+
+#: options.h:825
+msgid "Strip debugging information"
+msgstr "Elimina le informazioni di debug"
+
+#: options.h:827
+msgid "Emit only debug line number information"
+msgstr "Emette solo le informazioni sul numero di riga di debug"
+
+#: options.h:829
+msgid "Strip debug symbols that are unused by gdb (at least versions <= 6.7)"
+msgstr "Elimina i simboli di debug che sono inutilizzati da gdb (almeno nelle versioni <= 6.7)"
+
+#: options.h:832
+msgid "Strip LTO intermediate code sections"
+msgstr "Rimuove le sezioni di codice intermedie LTO"
+
+#: options.h:835
+msgid "(ARM only) The maximum distance from instructions in a group of sections to their stubs. Negative values mean stubs are always after the group. 1 means using default size.\n"
+msgstr "(solo ARM) La distanza massima dalle istruzioni in un gruppo di sezioni ai loro stub. Valori negativi corrispondono a stub che sono sempre dopo il gruppo, 1 significa usare la dimensione predefinita.\n"
+
+#: options.h:838 options.h:852 options.h:956 options.h:975
+msgid "SIZE"
+msgstr "DIMENSIONE"
+
+#: options.h:841
+msgid "Use less memory and more disk I/O (included only for compatibility with GNU ld)"
+msgstr "Usa meno memoria e più I/O del disco (incluso solo per compatibilità con ld di GNU)"
+
+#: options.h:845 options.h:848
+msgid "Generate shared library"
+msgstr "Genera una libreria condivisa"
+
+#: options.h:851
+msgid "Stack size when -fsplit-stack function calls non-split"
+msgstr "Dimensione dello stack quando la funzione -fsplit-stack chiama non-split"
+
+#: options.h:857
+msgid "Do not link against shared libraries"
+msgstr "Non esegue il link alle librerie condivise"
+
+#: options.h:860
+msgid "Identical Code Folding. '--icf=safe' folds only ctors and dtors."
+msgstr "Ripiegamento di codice identico (ICF). \"--icf=safe\" ripiega solo ctors e dtors."
+
+#: options.h:866
+msgid "Number of iterations of ICF (default 2)"
+msgstr "Numero di iterazioni di ICF (predefinito 2)"
+
+#: options.h:866 options.h:899 options.h:901 options.h:903 options.h:905
+msgid "COUNT"
+msgstr "NUMERO"
+
+#: options.h:869
+msgid "List folded identical sections on stderr"
+msgstr "Elenca le sezioni ripiegate identiche sullo stderr"
+
+#: options.h:870
+msgid "Do not list folded identical sections"
+msgstr "Non elenca le sezioni ripiegate identiche"
+
+#: options.h:873
+msgid "Do not fold this symbol during ICF"
+msgstr "Non ripiega questo simbolo durante l'ICF"
+
+#: options.h:876
+msgid "Remove unused sections"
+msgstr "Rimuove le sezioni inutilizzate"
+
+#: options.h:877
+msgid "Don't remove unused sections (default)"
+msgstr "Non rimuove le sezioni inutilizzate (predefinito)"
+
+#: options.h:880
+msgid "List removed unused sections on stderr"
+msgstr "Elenca le sezioni inutilizzate rimosse su stderr"
+
+#: options.h:881
+msgid "Do not list removed unused sections"
+msgstr "Non elenca le sezioni inutilizzate rimosse"
+
+#: options.h:884
+msgid "Print resource usage statistics"
+msgstr "Stampa le statistiche sull'uso delle risorse"
+
+#: options.h:887
+msgid "Set target system root directory"
+msgstr "Imposta la directory root del sistema obiettivo"
+
+#: options.h:890
+msgid "Print the name of each input file"
+msgstr "Stampa il nome di ciascun file di input"
+
+#: options.h:893
+msgid "Read linker script"
+msgstr "Legge lo script del linker"
+
+#: options.h:896
+msgid "Run the linker multi-threaded"
+msgstr "Esegue il linker con thread multiplo"
+
+#: options.h:897
+msgid "Do not run the linker multi-threaded"
+msgstr "Non esegue il linker con thread multiplo"
+
+#: options.h:899
+msgid "Number of threads to use"
+msgstr "Numero di thread da usare"
+
+#: options.h:901
+msgid "Number of threads to use in initial pass"
+msgstr "Numero di thread da usare nella passata iniziale"
+
+#: options.h:903
+msgid "Number of threads to use in middle pass"
+msgstr "Numero di thread da usare nella passata intermedia"
+
+#: options.h:905
+msgid "Number of threads to use in final pass"
+msgstr "Numero di thread da usare nella passata finale"
+
+#: options.h:908
+msgid "Set the address of the bss segment"
+msgstr "Imposta l'indirizzo del segmento bss"
+
+#: options.h:910
+msgid "Set the address of the data segment"
+msgstr "Imposta l'indirizzo del segmento data"
+
+#: options.h:912
+msgid "Set the address of the text segment"
+msgstr "Imposta l'indirizzo del segmento text"
+
+#: options.h:915
+msgid "Create undefined reference to SYMBOL"
+msgstr "Crea riferimenti non definiti al SIMBOLO"
+
+#: options.h:918
+msgid "Synonym for --debug=files"
+msgstr "Sinonimo per --debug=file"
+
+#: options.h:921
+msgid "Read version script"
+msgstr "Legge lo script di versione"
+
+#: options.h:924
+msgid "Warn about duplicate common symbols"
+msgstr "Avvisa in caso di simboli comuni duplicati"
+
+#: options.h:925
+msgid "Do not warn about duplicate common symbols (default)"
+msgstr "Non avvisa in caso di simboli comuni duplicati (predefinito)"
+
+#: options.h:928
+msgid "Warn when skipping an incompatible library"
+msgstr "Avverte quando viene saltata una libreria incompatibile"
+
+#: options.h:929
+msgid "Don't warn when skipping an incompatible library"
+msgstr "Non avverte quando viene saltata una libreria incompatibile"
+
+#: options.h:932
+msgid "Include all archive contents"
+msgstr "Include tutto il contenuto dell'archivio"
+
+#: options.h:933
+msgid "Include only needed archive contents"
+msgstr "Include solo i contenuti necessari dell'archivio"
+
+#: options.h:936
+msgid "Use wrapper functions for SYMBOL"
+msgstr "Usa le funzioni wrapper per il SIMBOLO"
+
+#: options.h:939
+msgid "Trace references to symbol"
+msgstr "Traccia i riferimenti al simbolo"
+
+#: options.h:942
+msgid "Default search path for Solaris compatibility"
+msgstr "Percorso di ricerca predefinito per compatibilità con Solaris"
+
+#: options.h:943
+msgid "PATH"
+msgstr "PERCORSO"
+
+#: options.h:946
+msgid "Start a library search group"
+msgstr "Avvia un gruppo di ricerca di librerie"
+
+#: options.h:948
+msgid "End a library search group"
+msgstr "Termina un gruppo di ricerca di librerie"
+
+#: options.h:953
+msgid "Sort dynamic relocs"
+msgstr "Ordina le rilocazioni dinamiche"
+
+#: options.h:954
+msgid "Do not sort dynamic relocs"
+msgstr "Non ordina le rilocazioni dinamiche"
+
+#: options.h:956
+msgid "Set common page size to SIZE"
+msgstr "Imposta la dimensione comune della pagina a DIMENSIONE"
+
+#: options.h:961
+msgid "Mark output as requiring executable stack"
+msgstr "Marca l'output come richiedente uno stack eseguibile"
+
+#: options.h:963
+msgid "Mark DSO to be initialized first at runtime"
+msgstr "Marca DSO per essere inizializzato per primo durante l'esecuzione"
+
+#: options.h:966
+msgid "Mark object to interpose all DSOs but executable"
+msgstr "Marca l'oggetto per interporre tutti i DSO ad eccezione degli eseguibili"
+
+#: options.h:969
+msgid "Mark object for lazy runtime binding (default)"
+msgstr "Marca l'oggetto per l'associazione durante l'esecuzione apatica (predefinita)"
+
+#: options.h:972
+msgid "Mark object requiring immediate process"
+msgstr "Marca l'oggetto come richiedente una elaborazione immediata"
+
+#: options.h:975
+msgid "Set maximum page size to SIZE"
+msgstr "Imposta la dimensione massima della pagina a DIMENSIONE"
+
+#: options.h:978
+msgid "Do not create copy relocs"
+msgstr "Non crea rilocazioni copia"
+
+#: options.h:980
+msgid "Mark object not to use default search paths"
+msgstr "Marca l'oggetto per non usare i percorsi di ricerca predefiniti"
+
+#: options.h:983
+msgid "Mark DSO non-deletable at runtime"
+msgstr "Marca DSO come non eliminabile durante l'esecuzione"
+
+#: options.h:986
+msgid "Mark DSO not available to dlopen"
+msgstr "Marca DSO come non disponibile per dlopen"
+
+#: options.h:989
+msgid "Mark DSO not available to dldump"
+msgstr "Marca DSO come non disponibile per dldump"
+
+#: options.h:992
+msgid "Mark output as not requiring executable stack"
+msgstr "Marca l'output come non richiedente uno stack eseguibile"
+
+#: options.h:994
+msgid "Mark object for immediate function binding"
+msgstr "Marca l'oggetto per l'associazione alla funziona immediata"
+
+#: options.h:997
+msgid "Mark DSO to indicate that needs immediate $ORIGIN processing at runtime"
+msgstr "Marca DSO per indicare che necessita dell'elaborazione dell'immediato $ORIGIN durante l'esecuzione"
+
+#: options.h:1000
+msgid "Where possible mark variables read-only after relocation"
+msgstr "Dove possibile contrassegna in sola lettura le variabili dopo la rilocazione"
+
+#: options.h:1001
+msgid "Don't mark variables read-only after relocation"
+msgstr "Non contrassegna in sola lettura le variabili dopo la rilocazione"
+
+#: output.cc:1132
+msgid "section group retained but group element discarded"
+msgstr "gruppo di sezione conservato ma elemento del gruppo scartato"
+
+#: output.cc:1860
+#, c-format
+msgid "invalid alignment %lu for section \"%s\""
+msgstr "allineamento %lu non valido per la sezione \"%s\""
+
+#: output.cc:3573
+#, c-format
+msgid "dot moves backward in linker script from 0x%llx to 0x%llx"
+msgstr "nello script del linker dot retrocede da 0x%llx a 0x%llx"
+
+#: output.cc:3576
+#, c-format
+msgid "address of section '%s' moves backward from 0x%llx to 0x%llx"
+msgstr "l'indirizzo della sezione \"%s\" retrocede da 0x%llx a 0x%llx"
+
+#: output.cc:3755
+#, c-format
+msgid "nobits section %s may not precede progbits section %s in same segment"
+msgstr "la sezione nobits %s non può precedere la sezione progbits %s nello stesso segmento"
+
+#: output.cc:3907 output.cc:3975
+#, c-format
+msgid "%s: open: %s"
+msgstr "%s: open: %s"
+
+#: output.cc:3996
+#, c-format
+msgid "%s: mremap: %s"
+msgstr "%s: mremap: %s"
+
+#: output.cc:4005
+#, c-format
+msgid "%s: mmap: %s"
+msgstr "%s: mmap: %s"
+
+#: output.cc:4085
+#, c-format
+msgid "%s: mmap: failed to allocate %lu bytes for output file: %s"
+msgstr "%s: mmap: impossibile allocare %lu byte per il file di output: %s"
+
+#: output.cc:4096
+#, c-format
+msgid "%s: munmap: %s"
+msgstr "%s: munmap: %s"
+
+#: output.cc:4115
+#, c-format
+msgid "%s: write: unexpected 0 return-value"
+msgstr "%s: write: restituito il valore inaspettato 0"
+
+#: output.cc:4117
+#, c-format
+msgid "%s: write: %s"
+msgstr "%s: write: %s"
+
+#: output.cc:4132
+#, c-format
+msgid "%s: close: %s"
+msgstr "%s: close: %s"
+
+#: output.h:520
+msgid "** section headers"
+msgstr "** intestazioni di sezione"
+
+#: output.h:565
+msgid "** segment headers"
+msgstr "** intestazioni di segmento"
+
+#: output.h:613
+msgid "** file header"
+msgstr "** intestazione del file"
+
+#: output.h:833
+msgid "** fill"
+msgstr "** riempimento"
+
+#: output.h:987
+msgid "** string table"
+msgstr "** tabella di stringhe"
+
+#: output.h:1300
+msgid "** dynamic relocs"
+msgstr "** rilocazioni dinamiche"
+
+#: output.h:1301 output.h:1637
+msgid "** relocs"
+msgstr "** rilocazioni"
+
+#: output.h:1662
+msgid "** group"
+msgstr "** gruppo"
+
+#: output.h:1774
+msgid "** GOT"
+msgstr "** GOT"
+
+#: output.h:1916
+msgid "** dynamic"
+msgstr "** dinamico"
+
+#: output.h:2039
+msgid "** symtab xindex"
+msgstr "** xindex symtab"
+
+#: parameters.cc:172
+#, c-format
+msgid "unrecognized output format %s"
+msgstr "formato di output non riconosciuto %s"
+
+#: plugin.cc:106
+#, c-format
+msgid "%s: could not load plugin library"
+msgstr "%s: impossibile caricare la libreria di plugin"
+
+#: plugin.cc:116
+#, c-format
+msgid "%s: could not find onload entry point"
+msgstr "%s: impossibile trovare il punto di ingresso di onload"
+
+#: plugin.cc:426
+msgid "Input files added by plug-ins in --incremental mode not supported yet.\n"
+msgstr "File di input aggiunti dai plugin in modalità --incremental non ancora supportati.\n"
+
+#: powerpc.cc:1502 sparc.cc:2307 x86_64.cc:1632
+#, c-format
+msgid "%s: unsupported REL reloc section"
+msgstr "%s: sezione di rilocazione REL non supportata"
+
+#: readsyms.cc:191
+#, c-format
+msgid "%s: file is empty"
+msgstr "%s: il file è vuoto"
+
+#. Here we have to handle any other input file types we need.
+#: readsyms.cc:575
+#, c-format
+msgid "%s: not an object or archive"
+msgstr "%s: non è un oggetto o un archivio"
+
+#: reduced_debug_output.cc:236
+msgid "Debug abbreviations extend beyond .debug_abbrev section; failed to reduce debug abbreviations"
+msgstr "Le abbreviazioni di debug si estendono oltre la sezione .debug_abbrev, impossibile ridurle"
+
+#: reduced_debug_output.cc:322
+msgid "Extremely large compile unit in debug info; failed to reduce debug info"
+msgstr "Unità di compilazione estremamente grande nelle informazioni di debug, impossibile ridurle"
+
+#: reduced_debug_output.cc:330
+msgid "Debug info extends beyond .debug_info section;failed to reduce debug info"
+msgstr "Le informazioni di debug si estendono oltre la sezione .debug_info, impossibile ridurle"
+
+#: reduced_debug_output.cc:350 reduced_debug_output.cc:392
+msgid "Invalid DIE in debug info; failed to reduce debug info"
+msgstr "DIE non valido nelle informazioni di debug, impossibile ridurle"
+
+#: reduced_debug_output.cc:373
+msgid "Debug info extends beyond .debug_info section; failed to reduce debug info"
+msgstr "Le informazioni di debug si estendono oltre la sezione .debug_info, impossibile ridurle"
+
+#: reloc.cc:297 reloc.cc:858
+#, c-format
+msgid "relocation section %u uses unexpected symbol table %u"
+msgstr "la sezione di rilocazione %u usa una tabella dei simboli %u inattesa"
+
+#: reloc.cc:312 reloc.cc:875
+#, c-format
+msgid "unexpected entsize for reloc section %u: %lu != %u"
+msgstr "entsize inattesa per la sezione di rilocazione %u: %lu != %u"
+
+#: reloc.cc:321 reloc.cc:884
+#, c-format
+msgid "reloc section %u size %lu uneven"
+msgstr "sezione di rilocazione %u di dimensione %lu irregolare"
+
+#: reloc.cc:1203
+#, c-format
+msgid "could not convert call to '%s' to '%s'"
+msgstr "impossibile convertire la chiamata a \"%s\" su \"%s\""
+
+#: reloc.cc:1343
+#, c-format
+msgid "reloc section size %zu is not a multiple of reloc size %d\n"
+msgstr "la dimensione %zu della sezione di rilocazione non è un multiplo di quella di rilocazione %d\n"
+
+#. We should only see externally visible symbols in the symbol
+#. table.
+#: resolve.cc:191
+msgid "invalid STB_LOCAL symbol in external symbols"
+msgstr "simbolo STB_LOCAL non valido nei simboli esterni"
+
+#. Any target which wants to handle STB_LOOS, etc., needs to
+#. define a resolve method.
+#: resolve.cc:197
+msgid "unsupported symbol binding"
+msgstr "associazione di simboli non supportata"
+
+#. A dynamic object cannot reference a hidden or internal symbol
+#. defined in another object.
+#: resolve.cc:266
+#, c-format
+msgid "%s symbol '%s' in %s is referenced by DSO %s"
+msgstr "Il simbolo %s \"%s\" in %s è referenziato da %s DSO"
+
+#: resolve.cc:326
+#, c-format
+msgid "common of '%s' overriding smaller common"
+msgstr "il comune di \"%s\" annulla il comune più piccolo"
+
+#: resolve.cc:331
+#, c-format
+msgid "common of '%s' overidden by larger common"
+msgstr "il comune di \"%s\" è annullato dal comune più grande"
+
+#: resolve.cc:336
+#, c-format
+msgid "multiple common of '%s'"
+msgstr "comune multiplo di \"%s\""
+
+#: resolve.cc:442
+#, c-format
+msgid "multiple definition of '%s'"
+msgstr "definizione multipla di \"%s\""
+
+#: resolve.cc:481
+#, c-format
+msgid "definition of '%s' overriding common"
+msgstr "la definizione di \"%s\" annulla il comune"
+
+#: resolve.cc:516
+#, c-format
+msgid "definition of '%s' overriding dynamic common definition"
+msgstr "la definizione di \"%s\" annulla la definizione del comune dinamico"
+
+#: resolve.cc:636
+#, c-format
+msgid "common '%s' overridden by previous definition"
+msgstr "\"%s\" comune è annullato dalla definizione precedente"
+
+#: resolve.cc:766 resolve.cc:778
+msgid "command line"
+msgstr "riga di comando"
+
+#: script-sections.cc:690
+msgid "dot may not move backward"
+msgstr "dot non può retrocedere"
+
+#: script-sections.cc:757
+msgid "** expression"
+msgstr "** espressione"
+
+#: script-sections.cc:941
+msgid "fill value is not absolute"
+msgstr "il valore di riempimento non è assoluto"
+
+#: script-sections.cc:1913
+#, c-format
+msgid "alignment of section %s is not absolute"
+msgstr "l'allineamento della sezione %s non è assoluto"
+
+#: script-sections.cc:1957
+#, c-format
+msgid "subalign of section %s is not absolute"
+msgstr "il sotto-allineamento della sezione %s non è assoluto"
+
+#: script-sections.cc:1972
+#, c-format
+msgid "fill of section %s is not absolute"
+msgstr "il riempimento della sezione %s non è assoluto"
+
+#: script-sections.cc:2048
+msgid "SPECIAL constraints are not implemented"
+msgstr "i vincoli SPECIAL non sono implementati"
+
+#: script-sections.cc:2090
+msgid "mismatched definition for constrained sections"
+msgstr "definizione non corrispondente per le sezioni vincolate"
+
+#: script-sections.cc:2634
+msgid "DATA_SEGMENT_ALIGN may only appear once in a linker script"
+msgstr "DATA_SEGMENT_ALIGN può comparire solo una volta in uno script del linker"
+
+#: script-sections.cc:2649
+msgid "DATA_SEGMENT_RELRO_END may only appear once in a linker script"
+msgstr "DATA_SEGMENT_RELRO_END può comparire solo una volta in uno script del linker"
+
+#: script-sections.cc:2654
+msgid "DATA_SEGMENT_RELRO_END must follow DATA_SEGMENT_ALIGN"
+msgstr "DATA_SEGMENT_RELRO_END deve seguire DATA_SEGMENT_ALIGN"
+
+#: script-sections.cc:2826
+msgid "no matching section constraint"
+msgstr "nessuna corrispondenza per il vincolo di sezione"
+
+#: script-sections.cc:3151
+msgid "TLS sections are not adjacent"
+msgstr "le sezioni TLS non sono adiacenti"
+
+#: script-sections.cc:3280
+msgid "allocated section not in any segment"
+msgstr "la sezione allocata non è in alcun segmento"
+
+#: script-sections.cc:3309
+#, c-format
+msgid "no segment %s"
+msgstr "nessun segmento %s"
+
+#: script-sections.cc:3323
+msgid "section in two PT_LOAD segments"
+msgstr "sezione in due segmenti PT_LOAD"
+
+#: script-sections.cc:3330
+msgid "allocated section not in any PT_LOAD segment"
+msgstr "la sezione allocata non è in alcun segmento PT_LOAD"
+
+#: script-sections.cc:3358
+msgid "may only specify load address for PT_LOAD segment"
+msgstr "può solo specificare l'indirizzo di caricamento per il segmento PT_LOAD"
+
+#: script-sections.cc:3382
+#, c-format
+msgid "PHDRS load address overrides section %s load address"
+msgstr "l'indirizzo di caricamento PHDRS sovrascrive quello di caricamento della sezione %s"
+
+#. We could support this if we wanted to.
+#: script-sections.cc:3393
+msgid "using only one of FILEHDR and PHDRS is not currently supported"
+msgstr "l'uso individuale di FILEHDR e PHDRS non è attualmente supportato"
+
+#: script-sections.cc:3408
+msgid "sections loaded on first page without room for file and program headers are not supported"
+msgstr "le sezioni caricate sulla prima pagina senza spazio per i file e le intestazioni di programma non sono supportate"
+
+#: script-sections.cc:3414
+msgid "using FILEHDR and PHDRS on more than one PT_LOAD segment is not currently supported"
+msgstr "l'uso di FILEHDR e PHDRS in più di un segmento PT_LOAD non è attualmente supportato"
+
+#: script.cc:1072
+msgid "invalid use of PROVIDE for dot symbol"
+msgstr "uso non valido di PROVIDE per il simbolo dot"
+
+#: script.cc:2132
+#, c-format
+msgid "%s:%d:%d: %s"
+msgstr "%s:%d:%d: %s"
+
+#. There are some options that we could handle here--e.g.,
+#. -lLIBRARY. Should we bother?
+#: script.cc:2297
+#, c-format
+msgid "%s:%d:%d: ignoring command OPTION; OPTION is only valid for scripts specified via -T/--script"
+msgstr "%s:%d:%d: comando OPTION ignorato; OPTION è valido solo per gli script specificati attraverso -T/--script"
+
+#: script.cc:2362
+#, c-format
+msgid "%s:%d:%d: ignoring SEARCH_DIR; SEARCH_DIR is only valid for scripts specified via -T/--script"
+msgstr "%s:%d:%d: SEARCH_DIR ignorato; SEARCH_DIR è valido solo per gli script specificati attraverso -T/--script"
+
+#: script.cc:2606 script.cc:2620
+#, c-format
+msgid "%s:%d:%d: DATA_SEGMENT_ALIGN not in SECTIONS clause"
+msgstr "%s:%d:%d: DATA_SEGMENT_ALIGN non è nella direttiva SECTIONS"
+
+#: script.cc:2739
+msgid "unknown PHDR type (try integer)"
+msgstr "tipo PHDR sconosciuto (provare con intero)"
+
+#: stringpool.cc:528
+#, c-format
+msgid "%s: %s entries: %zu; buckets: %zu\n"
+msgstr "%s: %s voci: %zu; bucket: %zu\n"
+
+#: stringpool.cc:532
+#, c-format
+msgid "%s: %s entries: %zu\n"
+msgstr "%s: %s voci: %zu\n"
+
+#: stringpool.cc:535
+#, c-format
+msgid "%s: %s Stringdata structures: %zu\n"
+msgstr "%s: %s strutture Stringdata: %zu\n"
+
+#: symtab.cc:857
+#, c-format
+msgid "%s: reference to %s"
+msgstr "%s: riferimento a %s"
+
+#: symtab.cc:859
+#, c-format
+msgid "%s: definition of %s"
+msgstr "%s: definizione di %s"
+
+#: symtab.cc:1052
+#, c-format
+msgid "bad global symbol name offset %u at %zu"
+msgstr "posizione %u errata del nome di simbolo globale alla %zu"
+
+#: symtab.cc:1278
+msgid "--just-symbols does not make sense with a shared object"
+msgstr "--just-symbols non ha senso con un oggetto condiviso"
+
+#: symtab.cc:1284
+msgid "too few symbol versions"
+msgstr "troppo poche versioni del simbolo"
+
+#: symtab.cc:1333
+#, c-format
+msgid "bad symbol name offset %u at %zu"
+msgstr "posizione %u errata del nome del simbolo alla %zu"
+
+#: symtab.cc:1396
+#, c-format
+msgid "versym for symbol %zu out of range: %u"
+msgstr "versym per il simbolo %zu fuori dall'intervallo: %u"
+
+#: symtab.cc:1404
+#, c-format
+msgid "versym for symbol %zu has no name: %u"
+msgstr "versym per il simbolo %zu non ha nome: %u"
+
+#: symtab.cc:2549 symtab.cc:2681
+#, c-format
+msgid "%s: unsupported symbol section 0x%x"
+msgstr "%s: sezione del simbolo non supportata 0x%x"
+
+#: symtab.cc:2933
+#, c-format
+msgid "%s: symbol table entries: %zu; buckets: %zu\n"
+msgstr "%s: voci della tabella dei simboli: %zu; bucket: %zu\n"
+
+#: symtab.cc:2936
+#, c-format
+msgid "%s: symbol table entries: %zu\n"
+msgstr "%s: voci della tabella dei simboli: %zu\n"
+
+#: symtab.cc:3007
+#, c-format
+msgid "while linking %s: symbol '%s' defined in multiple places (possible ODR violation):"
+msgstr "durante il link di %s: simbolo \"%s\" definito in posizioni multiple (possibile violazione della ODR):"
+
+#: target-reloc.h:259
+msgid "relocation refers to discarded comdat section"
+msgstr "la rilocazione si riferisce a una sezione comdat scartata"
+
+#: target-reloc.h:298
+#, c-format
+msgid "reloc has bad offset %zu"
+msgstr "la rilocazione ha una posizione %zu errata"
+
+#: target.cc:90
+#, c-format
+msgid "%s: unsupported ELF file type %d"
+msgstr "%s: tipo di file ELF non supportato %d"
+
+#: target.cc:157
+#, c-format
+msgid "linker does not include stack split support required by %s"
+msgstr "il linker non include il supporto allo \"stack split\" richiesto da %s"
+
+#: tls.h:59
+msgid "TLS relocation out of range"
+msgstr "rilocazione TLS fuori dall'intervallo"
+
+#: tls.h:73
+msgid "TLS relocation against invalid instruction"
+msgstr "rilocazione TLS contro una istruzione non valida"
+
+#. This output is intended to follow the GNU standards.
+#: version.cc:65
+#, c-format
+msgid "Copyright 2008 Free Software Foundation, Inc.\n"
+msgstr "Copyright 2008 Free Software Foundation, Inc.\n"
+
+#: version.cc:66
+#, c-format
+msgid ""
+"This program is free software; you may redistribute it under the terms of\n"
+"the GNU General Public License version 3 or (at your option) a later version.\n"
+"This program has absolutely no warranty.\n"
+msgstr ""
+"Questo programma è software libero; siete liberi di ridistribuirlo secondo i termini della\n"
+"GNU General Public License versione 3 o (a scelta) una versione più recente.\n"
+"Questo programma non ha assolutamente alcuna garanzia.\n"
+
+#: workqueue-threads.cc:106
+#, c-format
+msgid "%s failed: %s"
+msgstr "%s non riuscito: %s"
+
+#: x86_64.cc:2184
+#, c-format
+msgid "unsupported reloc type %u"
+msgstr "tipo di rilocazione non supportato %u"
+
+#: x86_64.cc:2524
+#, c-format
+msgid "unsupported reloc %u against local symbol"
+msgstr "rilocazione %u contro un simbolo locale non supportata"
diff --git a/binutils-2.22/gold/powerpc.cc b/binutils-2.22/gold/powerpc.cc
index a09c50b..d8e8b82 100644
--- a/binutils-2.22/gold/powerpc.cc
+++ b/binutils-2.22/gold/powerpc.cc
@@ -1,6 +1,6 @@
// powerpc.cc -- powerpc target support for gold.
-// Copyright 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
// Written by David S. Miller <davem@davemloft.net>
// and David Edelsohn <edelsohn@gnu.org>
@@ -62,20 +62,20 @@ class Target_powerpc : public Sized_target<size, big_endian>
{
}
- // Process the relocations to determine unreferenced sections for
+ // Process the relocations to determine unreferenced sections for
// garbage collection.
void
gc_process_relocs(Symbol_table* symtab,
- Layout* layout,
- Sized_relobj_file<size, big_endian>* object,
- unsigned int data_shndx,
- unsigned int sh_type,
- const unsigned char* prelocs,
- size_t reloc_count,
- Output_section* output_section,
- bool needs_special_offset_handling,
- size_t local_symbol_count,
- const unsigned char* plocal_symbols);
+ Layout* layout,
+ Sized_relobj_file<size, big_endian>* object,
+ unsigned int data_shndx,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ size_t local_symbol_count,
+ const unsigned char* plocal_symbols);
// Scan the relocations to look for symbol adjustments.
void
@@ -210,21 +210,21 @@ class Target_powerpc : public Sized_target<size, big_endian>
inline bool
local_reloc_may_be_function_pointer(Symbol_table* , Layout* ,
Target_powerpc* ,
- Sized_relobj_file<size, big_endian>* ,
- unsigned int ,
- Output_section* ,
- const elfcpp::Rela<size, big_endian>& ,
+ Sized_relobj_file<size, big_endian>* ,
unsigned int ,
- const elfcpp::Sym<size, big_endian>&)
+ Output_section* ,
+ const elfcpp::Rela<size, big_endian>& ,
+ unsigned int ,
+ const elfcpp::Sym<size, big_endian>&)
{ return false; }
inline bool
global_reloc_may_be_function_pointer(Symbol_table* , Layout* ,
Target_powerpc* ,
- Sized_relobj_file<size, big_endian>* ,
- unsigned int ,
- Output_section* ,
- const elfcpp::Rela<size,
+ Sized_relobj_file<size, big_endian>* ,
+ unsigned int ,
+ Output_section* ,
+ const elfcpp::Rela<size,
big_endian>& ,
unsigned int , Symbol*)
{ return false; }
@@ -270,7 +270,7 @@ class Target_powerpc : public Sized_target<size, big_endian>
inline void
relocate_tls(const Relocate_info<size, big_endian>*,
Target_powerpc* target,
- size_t relnum, const elfcpp::Rela<size, big_endian>&,
+ size_t relnum, const elfcpp::Rela<size, big_endian>&,
unsigned int r_type, const Sized_symbol<size>*,
const Symbol_value<size>*,
unsigned char*,
@@ -330,7 +330,7 @@ class Target_powerpc : public Sized_target<size, big_endian>
// Copy a relocation against a global symbol.
void
copy_reloc(Symbol_table* symtab, Layout* layout,
- Sized_relobj_file<size, big_endian>* object,
+ Sized_relobj_file<size, big_endian>* object,
unsigned int shndx, Output_section* output_section,
Symbol* sym, const elfcpp::Rela<size, big_endian>& reloc)
{
@@ -389,6 +389,8 @@ Target::Target_info Target_powerpc<32, true>::powerpc_info =
0x10000000, // default_text_segment_address
64 * 1024, // abi_pagesize (overridable by -z max-page-size)
4 * 1024, // common_pagesize (overridable by -z common-page-size)
+ false, // isolate_execinstr
+ 0, // rosegment_gap
elfcpp::SHN_UNDEF, // small_common_shndx
elfcpp::SHN_UNDEF, // large_common_shndx
0, // small_common_section_flags
@@ -413,6 +415,8 @@ Target::Target_info Target_powerpc<32, false>::powerpc_info =
0x10000000, // default_text_segment_address
64 * 1024, // abi_pagesize (overridable by -z max-page-size)
4 * 1024, // common_pagesize (overridable by -z common-page-size)
+ false, // isolate_execinstr
+ 0, // rosegment_gap
elfcpp::SHN_UNDEF, // small_common_shndx
elfcpp::SHN_UNDEF, // large_common_shndx
0, // small_common_section_flags
@@ -437,6 +441,8 @@ Target::Target_info Target_powerpc<64, true>::powerpc_info =
0x10000000, // default_text_segment_address
64 * 1024, // abi_pagesize (overridable by -z max-page-size)
8 * 1024, // common_pagesize (overridable by -z common-page-size)
+ false, // isolate_execinstr
+ 0, // rosegment_gap
elfcpp::SHN_UNDEF, // small_common_shndx
elfcpp::SHN_UNDEF, // large_common_shndx
0, // small_common_section_flags
@@ -461,6 +467,8 @@ Target::Target_info Target_powerpc<64, false>::powerpc_info =
0x10000000, // default_text_segment_address
64 * 1024, // abi_pagesize (overridable by -z max-page-size)
8 * 1024, // common_pagesize (overridable by -z common-page-size)
+ false, // isolate_execinstr
+ 0, // rosegment_gap
elfcpp::SHN_UNDEF, // small_common_shndx
elfcpp::SHN_UNDEF, // large_common_shndx
0, // small_common_section_flags
@@ -952,7 +960,7 @@ static const unsigned int addis_r12_r2 = 0x3d820000; /* addis %r12,%r2,xxx@h
static const unsigned int std_r2_40r1 = 0xf8410028; /* std %r2,40(%r1) */
static const unsigned int ld_r11_0r12 = 0xe96c0000; /* ld %r11,xxx+0@l(%r12) */
static const unsigned int ld_r2_0r12 = 0xe84c0000; /* ld %r2,xxx+8@l(%r12) */
- /* ld %r11,xxx+16@l(%r12) */
+ /* ld %r11,xxx+16@l(%r12) */
// Write out the PLT.
@@ -1311,27 +1319,27 @@ Target_powerpc<size, big_endian>::Scan::local(
// executable), we need to create a dynamic relocation for
// this location.
if (parameters->options().output_is_position_independent())
- {
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ {
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
check_non_pic(object, r_type);
- if (lsym.get_st_type() != elfcpp::STT_SECTION)
- {
- unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
- rela_dyn->add_local(object, r_sym, r_type, output_section,
+ if (lsym.get_st_type() != elfcpp::STT_SECTION)
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+ rela_dyn->add_local(object, r_sym, r_type, output_section,
data_shndx, reloc.get_r_offset(),
reloc.get_r_addend());
- }
- else
- {
+ }
+ else
+ {
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
- gold_assert(lsym.get_st_value() == 0);
- rela_dyn->add_local_relative(object, r_sym, r_type,
+ gold_assert(lsym.get_st_value() == 0);
+ rela_dyn->add_local_relative(object, r_sym, r_type,
output_section, data_shndx,
reloc.get_r_offset(),
- reloc.get_r_addend());
- }
- }
+ reloc.get_r_addend(), false);
+ }
+ }
break;
case elfcpp::R_POWERPC_REL24:
@@ -1352,8 +1360,8 @@ Target_powerpc<size, big_endian>::Scan::local(
case elfcpp::R_PPC64_TOC16_DS:
case elfcpp::R_PPC64_TOC16_LO_DS:
{
- // The symbol requires a GOT entry.
- Output_data_got<size, big_endian>* got;
+ // The symbol requires a GOT entry.
+ Output_data_got<size, big_endian>* got;
unsigned int r_sym;
got = target->got_section(symtab, layout);
@@ -1372,9 +1380,9 @@ Target_powerpc<size, big_endian>::Scan::local(
object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off);
rela_dyn->add_local_relative(object, r_sym,
elfcpp::R_POWERPC_RELATIVE,
- got, off, 0);
+ got, off, 0, false);
}
- }
+ }
else
got->add_local(object, r_sym, GOT_TYPE_STANDARD);
}
@@ -1446,8 +1454,8 @@ Target_powerpc<size, big_endian>::Scan::global(
// if the symbol is defined in the output file and is protected
// or hidden.
if (gsym->is_defined()
- && !gsym->is_from_dynobj()
- && !gsym->is_preemptible())
+ && !gsym->is_from_dynobj()
+ && !gsym->is_preemptible())
break;
target->make_plt_entry(symtab, layout, gsym);
break;
@@ -1459,38 +1467,38 @@ Target_powerpc<size, big_endian>::Scan::global(
case elfcpp::R_POWERPC_ADDR32:
case elfcpp::R_PPC64_ADDR64:
{
- // Make a PLT entry if necessary.
- if (gsym->needs_plt_entry())
- {
- target->make_plt_entry(symtab, layout, gsym);
- // Since this is not a PC-relative relocation, we may be
- // taking the address of a function. In that case we need to
- // set the entry in the dynamic symbol table to the address of
- // the PLT entry.
- if (gsym->is_from_dynobj() && !parameters->options().shared())
- gsym->set_needs_dynsym_value();
- }
- // Make a dynamic relocation if necessary.
- if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
- {
- if (gsym->may_need_copy_reloc())
- {
- target->copy_reloc(symtab, layout, object,
- data_shndx, output_section, gsym, reloc);
- }
- else if ((r_type == elfcpp::R_POWERPC_ADDR32
+ // Make a PLT entry if necessary.
+ if (gsym->needs_plt_entry())
+ {
+ target->make_plt_entry(symtab, layout, gsym);
+ // Since this is not a PC-relative relocation, we may be
+ // taking the address of a function. In that case we need to
+ // set the entry in the dynamic symbol table to the address of
+ // the PLT entry.
+ if (gsym->is_from_dynobj() && !parameters->options().shared())
+ gsym->set_needs_dynsym_value();
+ }
+ // Make a dynamic relocation if necessary.
+ if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
+ {
+ if (gsym->may_need_copy_reloc())
+ {
+ target->copy_reloc(symtab, layout, object,
+ data_shndx, output_section, gsym, reloc);
+ }
+ else if ((r_type == elfcpp::R_POWERPC_ADDR32
|| r_type == elfcpp::R_PPC64_ADDR64)
- && gsym->can_use_relative_reloc(false))
- {
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- rela_dyn->add_global_relative(gsym, elfcpp::R_POWERPC_RELATIVE,
+ && gsym->can_use_relative_reloc(false))
+ {
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ rela_dyn->add_global_relative(gsym, elfcpp::R_POWERPC_RELATIVE,
output_section, object,
data_shndx, reloc.get_r_offset(),
- reloc.get_r_addend());
- }
- else
- {
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ reloc.get_r_addend(), false);
+ }
+ else
+ {
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
check_non_pic(object, r_type);
if (gsym->is_from_dynobj()
@@ -1505,9 +1513,9 @@ Target_powerpc<size, big_endian>::Scan::global(
output_section, object,
data_shndx,
reloc.get_r_offset(),
- reloc.get_r_addend());
- }
- }
+ reloc.get_r_addend(), false);
+ }
+ }
}
break;
@@ -1552,31 +1560,31 @@ Target_powerpc<size, big_endian>::Scan::global(
case elfcpp::R_PPC64_TOC16_DS:
case elfcpp::R_PPC64_TOC16_LO_DS:
{
- // The symbol requires a GOT entry.
- Output_data_got<size, big_endian>* got;
+ // The symbol requires a GOT entry.
+ Output_data_got<size, big_endian>* got;
got = target->got_section(symtab, layout);
- if (gsym->final_value_is_known())
- got->add_global(gsym, GOT_TYPE_STANDARD);
- else
- {
- // If this symbol is not fully resolved, we need to add a
- // dynamic relocation for it.
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- if (gsym->is_from_dynobj()
- || gsym->is_undefined()
- || gsym->is_preemptible())
- got->add_global_with_rela(gsym, GOT_TYPE_STANDARD, rela_dyn,
- elfcpp::R_POWERPC_GLOB_DAT);
- else if (!gsym->has_got_offset(GOT_TYPE_STANDARD))
- {
+ if (gsym->final_value_is_known())
+ got->add_global(gsym, GOT_TYPE_STANDARD);
+ else
+ {
+ // If this symbol is not fully resolved, we need to add a
+ // dynamic relocation for it.
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ if (gsym->is_from_dynobj()
+ || gsym->is_undefined()
+ || gsym->is_preemptible())
+ got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, rela_dyn,
+ elfcpp::R_POWERPC_GLOB_DAT);
+ else if (!gsym->has_got_offset(GOT_TYPE_STANDARD))
+ {
unsigned int off = got->add_constant(0);
gsym->set_got_offset(GOT_TYPE_STANDARD, off);
rela_dyn->add_global_relative(gsym, elfcpp::R_POWERPC_RELATIVE,
- got, off, 0);
+ got, off, 0, false);
}
- }
+ }
}
break;
@@ -1788,20 +1796,20 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
case elfcpp::R_PPC64_GOT16_DS:
case elfcpp::R_PPC64_GOT16_LO_DS:
if (gsym != NULL)
- {
- gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
- got_offset = gsym->got_offset(GOT_TYPE_STANDARD);
- }
+ {
+ gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
+ got_offset = gsym->got_offset(GOT_TYPE_STANDARD);
+ }
else
- {
- unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
- got_offset = object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
- }
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+ gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
+ got_offset = object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
+ }
break;
// R_PPC_PLTREL24 is rather special. If non-zero,
- // the addend specifies the GOT pointer offset within .got2.
+ // the addend specifies the GOT pointer offset within .got2.
case elfcpp::R_PPC_PLTREL24:
if (addend >= 32768)
{
@@ -2131,7 +2139,8 @@ public:
: (big_endian ? "elf32ppc" : "elf32lppc")))
{ }
- Target* do_recognize(int machine, int, int)
+ virtual Target*
+ do_recognize(Input_file*, off_t, int machine, int, int)
{
switch (size)
{
@@ -2152,7 +2161,8 @@ public:
return this->instantiate_target();
}
- Target* do_instantiate_target()
+ virtual Target*
+ do_instantiate_target()
{ return new Target_powerpc<size, big_endian>(); }
};
diff --git a/binutils-2.22/gold/readsyms.cc b/binutils-2.22/gold/readsyms.cc
index 1e50942..8e52ccb 100644
--- a/binutils-2.22/gold/readsyms.cc
+++ b/binutils-2.22/gold/readsyms.cc
@@ -161,8 +161,10 @@ void
Read_symbols::run(Workqueue* workqueue)
{
// If we didn't queue a new task, then we need to explicitly unblock
- // the token.
- if (!this->do_read_symbols(workqueue))
+ // the token. If the object is a member of a lib group, however,
+ // the token was already added to the list of locks for the task,
+ // and it will be unblocked automatically at the end of the task.
+ if (!this->do_read_symbols(workqueue) && this->member_ == NULL)
workqueue->queue_soon(new Unblock_token(this->this_blocker_,
this->next_blocker_));
}
@@ -600,6 +602,7 @@ Add_symbols::run(Workqueue*)
if (!this->input_objects_->add_object(this->object_))
{
+ this->object_->discard_decompressed_sections();
gold_assert(this->sd_ != NULL);
delete this->sd_;
this->sd_ = NULL;
@@ -630,6 +633,7 @@ Add_symbols::run(Workqueue*)
}
this->object_->layout(this->symtab_, this->layout_, this->sd_);
this->object_->add_symbols(this->symtab_, this->sd_, this->layout_);
+ this->object_->discard_decompressed_sections();
delete this->sd_;
this->sd_ = NULL;
this->object_->release();
diff --git a/binutils-2.22/gold/reduced_debug_output.cc b/binutils-2.22/gold/reduced_debug_output.cc
index 93757bf..a6158fc 100644
--- a/binutils-2.22/gold/reduced_debug_output.cc
+++ b/binutils-2.22/gold/reduced_debug_output.cc
@@ -1,6 +1,6 @@
// reduced_debug_output.cc -- output reduced debugging information to save space
-// Copyright 2008, 2010 Free Software Foundation, Inc.
+// Copyright 2008, 2010, 2012 Free Software Foundation, Inc.
// Written by Caleb Howe <cshowe@google.com>.
// This file is part of gold.
@@ -60,9 +60,10 @@ Output_reduced_debug_info_section::get_die_end(
return false;
switch(form)
{
- case elfcpp::DW_FORM_null:
+ case elfcpp::DW_FORM_flag_present:
break;
case elfcpp::DW_FORM_strp:
+ case elfcpp::DW_FORM_sec_offset:
die += is64 ? 8 : 4;
break;
case elfcpp::DW_FORM_addr:
@@ -88,6 +89,7 @@ Output_reduced_debug_info_section::get_die_end(
break;
}
case elfcpp::DW_FORM_block:
+ case elfcpp::DW_FORM_exprloc:
LEB_decoded = read_unsigned_LEB_128(die, &LEB_size);
die += (LEB_decoded + LEB_size);
break;
@@ -106,6 +108,7 @@ Output_reduced_debug_info_section::get_die_end(
break;
case elfcpp::DW_FORM_data8:
case elfcpp::DW_FORM_ref8:
+ case elfcpp::DW_FORM_ref_sig8:
die += 8;
break;
case elfcpp::DW_FORM_ref_udata:
@@ -113,14 +116,20 @@ Output_reduced_debug_info_section::get_die_end(
read_unsigned_LEB_128(die, &LEB_size);
die += LEB_size;
break;
+ case elfcpp::DW_FORM_sdata:
+ read_signed_LEB_128(die, &LEB_size);
+ die += LEB_size;
+ break;
case elfcpp::DW_FORM_string:
{
size_t length = strlen(reinterpret_cast<char*>(die));
die += length + 1;
break;
}
- case elfcpp::DW_FORM_sdata:
case elfcpp::DW_FORM_indirect:
+ case elfcpp::DW_FORM_GNU_addr_index:
+ case elfcpp::DW_FORM_GNU_str_index:
+ default:
return false;
}
}
diff --git a/binutils-2.22/gold/reloc.h b/binutils-2.22/gold/reloc.h
index 02f91a4..4eca71a 100644
--- a/binutils-2.22/gold/reloc.h
+++ b/binutils-2.22/gold/reloc.h
@@ -1,6 +1,7 @@
// reloc.h -- relocate input files for gold -*- C++ -*-
-// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -37,7 +38,7 @@ namespace gold
class General_options;
class Object;
class Relobj;
-class Read_relocs_data;
+struct Read_relocs_data;
class Symbol;
class Layout;
class Output_data;
@@ -715,6 +716,122 @@ public:
{ This::template pcrela<64>(view, object, psymval, addend, address); }
};
+// Integer manipulation functions used by various targets when
+// performing relocations.
+
+template<int bits>
+class Bits
+{
+ public:
+ // Sign extend an n-bit unsigned integer stored in a uint32_t into
+ // an int32_t. BITS must be between 1 and 32.
+ static inline int32_t
+ sign_extend32(uint32_t val)
+ {
+ gold_assert(bits > 0 && bits <= 32);
+ if (bits == 32)
+ return static_cast<int32_t>(val);
+ uint32_t mask = (~static_cast<uint32_t>(0)) >> (32 - bits);
+ val &= mask;
+ uint32_t top_bit = 1U << (bits - 1);
+ int32_t as_signed = static_cast<int32_t>(val);
+ if ((val & top_bit) != 0)
+ as_signed -= static_cast<int32_t>(top_bit * 2);
+ return as_signed;
+ }
+
+ // Return true if VAL (stored in a uint32_t) has overflowed a signed
+ // value with BITS bits.
+ static inline bool
+ has_overflow32(uint32_t val)
+ {
+ gold_assert(bits > 0 && bits <= 32);
+ if (bits == 32)
+ return false;
+ int32_t max = (1 << (bits - 1)) - 1;
+ int32_t min = -(1 << (bits - 1));
+ int32_t as_signed = static_cast<int32_t>(val);
+ return as_signed > max || as_signed < min;
+ }
+
+ // Return true if VAL (stored in a uint32_t) has overflowed both a
+ // signed and an unsigned value. E.g.,
+ // Bits<8>::has_signed_unsigned_overflow32 would check -128 <= VAL <
+ // 255.
+ static inline bool
+ has_signed_unsigned_overflow32(uint32_t val)
+ {
+ gold_assert(bits > 0 && bits <= 32);
+ if (bits == 32)
+ return false;
+ int32_t max = static_cast<int32_t>((1U << bits) - 1);
+ int32_t min = -(1 << (bits - 1));
+ int32_t as_signed = static_cast<int32_t>(val);
+ return as_signed > max || as_signed < min;
+ }
+
+ // Select bits from A and B using bits in MASK. For each n in
+ // [0..31], the n-th bit in the result is chosen from the n-th bits
+ // of A and B. A zero selects A and a one selects B.
+ static inline uint32_t
+ bit_select32(uint32_t a, uint32_t b, uint32_t mask)
+ { return (a & ~mask) | (b & mask); }
+
+ // Sign extend an n-bit unsigned integer stored in a uint64_t into
+ // an int64_t. BITS must be between 1 and 64.
+ static inline int64_t
+ sign_extend(uint64_t val)
+ {
+ gold_assert(bits > 0 && bits <= 64);
+ if (bits == 64)
+ return static_cast<int64_t>(val);
+ uint64_t mask = (~static_cast<uint64_t>(0)) >> (64 - bits);
+ val &= mask;
+ uint64_t top_bit = static_cast<uint64_t>(1) << (bits - 1);
+ int64_t as_signed = static_cast<int64_t>(val);
+ if ((val & top_bit) != 0)
+ as_signed -= static_cast<int64_t>(top_bit * 2);
+ return as_signed;
+ }
+
+ // Return true if VAL (stored in a uint64_t) has overflowed a signed
+ // value with BITS bits.
+ static inline bool
+ has_overflow(uint64_t val)
+ {
+ gold_assert(bits > 0 && bits <= 64);
+ if (bits == 64)
+ return false;
+ int64_t max = (static_cast<int64_t>(1) << (bits - 1)) - 1;
+ int64_t min = -(static_cast<int64_t>(1) << (bits - 1));
+ int64_t as_signed = static_cast<int64_t>(val);
+ return as_signed > max || as_signed < min;
+ }
+
+ // Return true if VAL (stored in a uint64_t) has overflowed both a
+ // signed and an unsigned value. E.g.,
+ // Bits<8>::has_signed_unsigned_overflow would check -128 <= VAL <
+ // 255.
+ static inline bool
+ has_signed_unsigned_overflow64(uint64_t val)
+ {
+ gold_assert(bits > 0 && bits <= 64);
+ if (bits == 64)
+ return false;
+ int64_t max = static_cast<int64_t>((static_cast<uint64_t>(1) << bits) - 1);
+ int64_t min = -(static_cast<int64_t>(1) << (bits - 1));
+ int64_t as_signed = static_cast<int64_t>(val);
+ return as_signed > max || as_signed < min;
+ }
+
+ // Select bits from A and B using bits in MASK. For each n in
+ // [0..31], the n-th bit in the result is chosen from the n-th bits
+ // of A and B. A zero selects A and a one selects B.
+ static inline uint64_t
+ bit_select64(uint64_t a, uint64_t b, uint64_t mask)
+ { return (a & ~mask) | (b & mask); }
+};
+
// Track relocations while reading a section. This lets you ask for
// the relocation at a certain offset, and see how relocs occur
// between points of interest.
@@ -756,6 +873,16 @@ class Track_relocs
int
advance(off_t offset);
+ // Checkpoint the current position in the reloc section.
+ section_size_type
+ checkpoint() const
+ { return this->pos_; }
+
+ // Reset the position to CHECKPOINT.
+ void
+ reset(section_size_type checkpoint)
+ { this->pos_ = checkpoint; }
+
private:
// The contents of the input object's reloc section.
const unsigned char* prelocs_;
diff --git a/binutils-2.22/gold/resolve.cc b/binutils-2.22/gold/resolve.cc
index 1119f38..0da8da2 100644
--- a/binutils-2.22/gold/resolve.cc
+++ b/binutils-2.22/gold/resolve.cc
@@ -296,7 +296,7 @@ Symbol_table::resolve(Sized_symbol<size>* to,
// Record if we've seen this symbol in a real ELF object (i.e., the
// symbol is referenced from outside the world known to the plugin).
- if (object->pluginobj() == NULL)
+ if (object->pluginobj() == NULL && !object->is_dynamic())
to->set_in_real_elf();
// If we're processing replacement files, allow new symbols to override
@@ -356,9 +356,15 @@ Symbol_table::resolve(Sized_symbol<size>* to,
&adjust_dyndef))
{
elfcpp::STB tobinding = to->binding();
+ typename Sized_symbol<size>::Value_type tovalue = to->value();
this->override(to, sym, st_shndx, is_ordinary, object, version);
- if (adjust_common_sizes && tosize > to->symsize())
- to->set_symsize(tosize);
+ if (adjust_common_sizes)
+ {
+ if (tosize > to->symsize())
+ to->set_symsize(tosize);
+ if (tovalue > to->value())
+ to->set_value(tovalue);
+ }
if (adjust_dyndef)
{
// We are overriding an UNDEF or WEAK UNDEF with a DYN DEF.
@@ -368,8 +374,13 @@ Symbol_table::resolve(Sized_symbol<size>* to,
}
else
{
- if (adjust_common_sizes && sym.get_st_size() > tosize)
- to->set_symsize(sym.get_st_size());
+ if (adjust_common_sizes)
+ {
+ if (sym.get_st_size() > tosize)
+ to->set_symsize(sym.get_st_size());
+ if (sym.get_st_value() > to->value())
+ to->set_value(sym.get_st_value());
+ }
if (adjust_dyndef)
{
// We are keeping a DYN DEF after seeing an UNDEF or WEAK UNDEF.
diff --git a/binutils-2.22/gold/script-sections.cc b/binutils-2.22/gold/script-sections.cc
index 1fad88d..f90c0b3 100644
--- a/binutils-2.22/gold/script-sections.cc
+++ b/binutils-2.22/gold/script-sections.cc
@@ -680,7 +680,7 @@ class Sections_element_assignment : public Sections_element
set_section_addresses(Symbol_table* symtab, Layout* layout,
uint64_t* dot_value, uint64_t*, uint64_t*)
{
- this->assignment_.set_if_absolute(symtab, layout, true, *dot_value);
+ this->assignment_.set_if_absolute(symtab, layout, true, *dot_value, NULL);
}
// Print for debugging.
@@ -714,7 +714,7 @@ class Sections_element_dot_assignment : public Sections_element
// output section definition the dot symbol is always considered
// to be absolute.
*dot_value = this->val_->eval_with_dot(symtab, layout, true, *dot_value,
- NULL, NULL, NULL);
+ NULL, NULL, NULL, false);
}
// Update the dot symbol while setting section addresses.
@@ -724,7 +724,7 @@ class Sections_element_dot_assignment : public Sections_element
uint64_t* load_address)
{
*dot_value = this->val_->eval_with_dot(symtab, layout, false, *dot_value,
- NULL, NULL, dot_alignment);
+ NULL, NULL, dot_alignment, false);
*load_address = *dot_value;
}
@@ -866,9 +866,11 @@ class Output_section_element_assignment : public Output_section_element
void
set_section_addresses(Symbol_table* symtab, Layout* layout, Output_section*,
uint64_t, uint64_t* dot_value, uint64_t*,
- Output_section**, std::string*, Input_section_list*)
+ Output_section** dot_section, std::string*,
+ Input_section_list*)
{
- this->assignment_.set_if_absolute(symtab, layout, true, *dot_value);
+ this->assignment_.set_if_absolute(symtab, layout, true, *dot_value,
+ *dot_section);
}
// Print for debugging.
@@ -892,20 +894,28 @@ class Output_section_element_dot_assignment : public Output_section_element
: val_(val)
{ }
+ // An assignment to dot within an output section is enough to force
+ // the output section to exist.
+ bool
+ needs_output_section() const
+ { return true; }
+
// Finalize the symbol.
void
finalize_symbols(Symbol_table* symtab, const Layout* layout,
uint64_t* dot_value, Output_section** dot_section)
{
*dot_value = this->val_->eval_with_dot(symtab, layout, true, *dot_value,
- *dot_section, dot_section, NULL);
+ *dot_section, dot_section, NULL,
+ true);
}
// Update the dot symbol while setting section addresses.
void
set_section_addresses(Symbol_table* symtab, Layout* layout, Output_section*,
uint64_t, uint64_t* dot_value, uint64_t*,
- Output_section**, std::string*, Input_section_list*);
+ Output_section** dot_section, std::string*,
+ Input_section_list*);
// Print for debugging.
void
@@ -936,7 +946,8 @@ Output_section_element_dot_assignment::set_section_addresses(
{
uint64_t next_dot = this->val_->eval_with_dot(symtab, layout, false,
*dot_value, *dot_section,
- dot_section, dot_alignment);
+ dot_section, dot_alignment,
+ true);
if (next_dot < *dot_value)
gold_error(_("dot may not move backward"));
if (next_dot > *dot_value && output_section != NULL)
@@ -1037,7 +1048,8 @@ Output_data_expression::do_write_to_buffer(unsigned char* buf)
{
uint64_t val = this->val_->eval_with_dot(this->symtab_, this->layout_,
true, this->dot_value_,
- this->dot_section_, NULL, NULL);
+ this->dot_section_, NULL, NULL,
+ false);
if (parameters->target().is_big_endian())
this->endian_write_to_buffer<true>(val, buf);
@@ -1187,7 +1199,7 @@ class Output_section_element_fill : public Output_section_element
Output_section* fill_section;
uint64_t fill_val = this->val_->eval_with_dot(symtab, layout, false,
*dot_value, *dot_section,
- &fill_section, NULL);
+ &fill_section, NULL, false);
if (fill_section != NULL)
gold_warning(_("fill value is not absolute"));
// FIXME: The GNU linker supports fill values of arbitrary length.
@@ -2108,13 +2120,13 @@ Output_section_definition::finalize_symbols(Symbol_table* symtab,
{
address = this->address_->eval_with_dot(symtab, layout, true,
*dot_value, NULL,
- NULL, NULL);
+ NULL, NULL, false);
}
if (this->align_ != NULL)
{
uint64_t align = this->align_->eval_with_dot(symtab, layout, true,
*dot_value, NULL,
- NULL, NULL);
+ NULL, NULL, false);
address = align_address(address, align);
}
*dot_value = address;
@@ -2303,7 +2315,7 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
else
address = this->address_->eval_with_dot(symtab, layout, true,
*dot_value, NULL, NULL,
- dot_alignment);
+ dot_alignment, false);
uint64_t align;
if (this->align_ == NULL)
{
@@ -2316,7 +2328,7 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
{
Output_section* align_section;
align = this->align_->eval_with_dot(symtab, layout, true, *dot_value,
- NULL, &align_section, NULL);
+ NULL, &align_section, NULL, false);
if (align_section != NULL)
gold_warning(_("alignment of section %s is not absolute"),
this->name_.c_str());
@@ -2401,7 +2413,7 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
laddr = this->load_address_->eval_with_dot(symtab, layout, true,
*dot_value,
this->output_section_,
- NULL, NULL);
+ NULL, NULL, false);
if (this->output_section_ != NULL)
this->output_section_->set_load_address(laddr);
}
@@ -2416,7 +2428,8 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
Output_section* subalign_section;
subalign = this->subalign_->eval_with_dot(symtab, layout, true,
*dot_value, NULL,
- &subalign_section, NULL);
+ &subalign_section, NULL,
+ false);
if (subalign_section != NULL)
gold_warning(_("subalign of section %s is not absolute"),
this->name_.c_str());
@@ -2431,7 +2444,7 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
uint64_t fill_val = this->fill_->eval_with_dot(symtab, layout, true,
*dot_value,
NULL, &fill_section,
- NULL);
+ NULL, false);
if (fill_section != NULL)
gold_warning(_("fill of section %s is not absolute"),
this->name_.c_str());
diff --git a/binutils-2.22/gold/script.cc b/binutils-2.22/gold/script.cc
index 7df0c9e..6a10c40 100644
--- a/binutils-2.22/gold/script.cc
+++ b/binutils-2.22/gold/script.cc
@@ -983,18 +983,20 @@ Symbol_assignment::sized_finalize(Symbol_table* symtab, const Layout* layout,
uint64_t final_val = this->val_->eval_maybe_dot(symtab, layout, true,
is_dot_available,
dot_value, dot_section,
- &section, NULL);
+ &section, NULL, false);
Sized_symbol<size>* ssym = symtab->get_sized_symbol<size>(this->sym_);
ssym->set_value(final_val);
if (section != NULL)
ssym->set_output_section(section);
}
-// Set the symbol value if the expression yields an absolute value.
+// Set the symbol value if the expression yields an absolute value or
+// a value relative to DOT_SECTION.
void
Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout,
- bool is_dot_available, uint64_t dot_value)
+ bool is_dot_available, uint64_t dot_value,
+ Output_section* dot_section)
{
if (this->sym_ == NULL)
return;
@@ -1002,8 +1004,9 @@ Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout,
Output_section* val_section;
uint64_t val = this->val_->eval_maybe_dot(symtab, layout, false,
is_dot_available, dot_value,
- NULL, &val_section, NULL);
- if (val_section != NULL)
+ dot_section, &val_section, NULL,
+ false);
+ if (val_section != NULL && val_section != dot_section)
return;
if (parameters->target().get_size() == 32)
@@ -1026,6 +1029,8 @@ Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout,
}
else
gold_unreachable();
+ if (val_section != NULL)
+ this->sym_->set_output_section(val_section);
}
// Print for debugging.
@@ -1215,7 +1220,7 @@ Script_options::set_section_addresses(Symbol_table* symtab, Layout* layout)
for (Symbol_assignments::iterator p = this->symbol_assignments_.begin();
p != this->symbol_assignments_.end();
++p)
- (*p)->set_if_absolute(symtab, layout, false, 0);
+ (*p)->set_if_absolute(symtab, layout, false, 0, NULL);
return this->script_sections_.set_section_addresses(symtab, layout);
}
@@ -1530,18 +1535,26 @@ read_input_script(Workqueue* workqueue, Symbol_table* symtab, Layout* layout,
return true;
}
-// Helper function for read_version_script() and
-// read_commandline_script(). Processes the given file in the mode
-// indicated by first_token and lex_mode.
+// Helper function for read_version_script(), read_commandline_script() and
+// script_include_directive(). Processes the given file in the mode indicated
+// by first_token and lex_mode.
static bool
read_script_file(const char* filename, Command_line* cmdline,
Script_options* script_options,
int first_token, Lex::Mode lex_mode)
{
- // TODO: if filename is a relative filename, search for it manually
- // using "." + cmdline->options()->search_path() -- not dirsearch.
Dirsearch dirsearch;
+ std::string name = filename;
+
+ // If filename is a relative filename, search for it manually using "." +
+ // cmdline->options()->library_path() -- not dirsearch.
+ if (!IS_ABSOLUTE_PATH(filename))
+ {
+ const General_options::Dir_list& search_path =
+ cmdline->options().library_path();
+ name = Dirsearch::find_file_in_dir_list(name, search_path, ".");
+ }
// The file locking code wants to record a Task, but we haven't
// started the workqueue yet. This is only for debugging purposes,
@@ -1552,7 +1565,7 @@ read_script_file(const char* filename, Command_line* cmdline,
Position_dependent_options posdep = cmdline->position_dependent_options();
if (posdep.format_enum() == General_options::OBJECT_FORMAT_BINARY)
posdep.set_format_enum(General_options::OBJECT_FORMAT_ELF);
- Input_file_argument input_argument(filename,
+ Input_file_argument input_argument(name.c_str(),
Input_file_argument::INPUT_FILE_TYPE_FILE,
"", false, posdep);
Input_file input_file(&input_argument);
@@ -3346,10 +3359,13 @@ script_parse_memory_attr(void* closurev, const char* attrs, size_t attrlen,
}
extern "C" void
-script_include_directive(void* closurev, const char*, size_t)
+script_include_directive(void* closurev, const char* filename, size_t length)
{
- // FIXME: Implement ?
- yyerror (closurev, _("GOLD does not currently support INCLUDE directives"));
+ Parser_closure* closure = static_cast<Parser_closure*>(closurev);
+ std::string name(filename, length);
+ Command_line* cmdline = closure->command_line();
+ read_script_file(name.c_str(), cmdline, &cmdline->script_options(),
+ PARSING_LINKER_SCRIPT, Lex::LINKER_SCRIPT);
}
// Functions for memory regions.
diff --git a/binutils-2.22/gold/script.h b/binutils-2.22/gold/script.h
index 73079a4..f41f438 100644
--- a/binutils-2.22/gold/script.h
+++ b/binutils-2.22/gold/script.h
@@ -90,20 +90,28 @@ class Expression
// the section address. If RESULT_ALIGNMENT is not NULL, this sets
// *RESULT_ALIGNMENT to the alignment of the value of that alignment
// is larger than *RESULT_ALIGNMENT; this will only be non-zero if
- // this is an ALIGN expression.
+ // this is an ALIGN expression. If IS_SECTION_DOT_ASSIGMENT is true,
+ // we are evaluating an assignment to dot within an output section,
+ // and an absolute value should be interpreted as an offset within
+ // the section.
uint64_t
eval_with_dot(const Symbol_table*, const Layout*, bool check_assertions,
uint64_t dot_value, Output_section* dot_section,
- Output_section** result_section, uint64_t* result_alignment);
+ Output_section** result_section, uint64_t* result_alignment,
+ bool is_section_dot_assignment);
// Return the value of an expression which may or may not be
// permitted to refer to the dot symbol, depending on
- // is_dot_available.
+ // is_dot_available. If IS_SECTION_DOT_ASSIGMENT is true,
+ // we are evaluating an assignment to dot within an output section,
+ // and an absolute value should be interpreted as an offset within
+ // the section.
uint64_t
eval_maybe_dot(const Symbol_table*, const Layout*, bool check_assertions,
bool is_dot_available, uint64_t dot_value,
Output_section* dot_section,
- Output_section** result_section, uint64_t* result_alignment);
+ Output_section** result_section, uint64_t* result_alignment,
+ bool is_section_dot_assignment);
// Print the expression to the FILE. This is for debugging.
virtual void
@@ -339,12 +347,12 @@ class Symbol_assignment
finalize_with_dot(Symbol_table*, const Layout*, uint64_t dot_value,
Output_section* dot_section);
- // Set the symbol value, but only if the value is absolute. This is
- // used while processing a SECTIONS clause. We assume that dot is
- // an absolute value here. We do not check assertions.
+ // Set the symbol value, but only if the value is absolute or relative to
+ // DOT_SECTION. This is used while processing a SECTIONS clause.
+ // We assume that dot is an absolute value here. We do not check assertions.
void
set_if_absolute(Symbol_table*, const Layout*, bool is_dot_available,
- uint64_t dot_value);
+ uint64_t dot_value, Output_section* dot_section);
const std::string&
name() const
diff --git a/binutils-2.22/gold/sparc.cc b/binutils-2.22/gold/sparc.cc
index 5f67a4e..7b78311 100644
--- a/binutils-2.22/gold/sparc.cc
+++ b/binutils-2.22/gold/sparc.cc
@@ -1,6 +1,6 @@
// sparc.cc -- sparc target support for gold.
-// Copyright 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
// Written by David S. Miller <davem@davemloft.net>.
// This file is part of gold.
@@ -58,26 +58,28 @@ class Target_sparc : public Sized_target<size, big_endian>
Target_sparc()
: Sized_target<size, big_endian>(&sparc_info),
- got_(NULL), plt_(NULL), rela_dyn_(NULL),
+ got_(NULL), plt_(NULL), rela_dyn_(NULL), rela_ifunc_(NULL),
copy_relocs_(elfcpp::R_SPARC_COPY), dynbss_(NULL),
- got_mod_index_offset_(-1U), tls_get_addr_sym_(NULL)
+ got_mod_index_offset_(-1U), tls_get_addr_sym_(NULL),
+ elf_machine_(sparc_info.machine_code), elf_flags_(0),
+ elf_flags_set_(false)
{
}
- // Process the relocations to determine unreferenced sections for
+ // Process the relocations to determine unreferenced sections for
// garbage collection.
void
gc_process_relocs(Symbol_table* symtab,
- Layout* layout,
- Sized_relobj_file<size, big_endian>* object,
- unsigned int data_shndx,
- unsigned int sh_type,
- const unsigned char* prelocs,
- size_t reloc_count,
- Output_section* output_section,
- bool needs_special_offset_handling,
- size_t local_symbol_count,
- const unsigned char* plocal_symbols);
+ Layout* layout,
+ Sized_relobj_file<size, big_endian>* object,
+ unsigned int data_shndx,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ size_t local_symbol_count,
+ const unsigned char* plocal_symbols);
// Scan the relocations to look for symbol adjustments.
void
@@ -154,6 +156,15 @@ class Target_sparc : public Sized_target<size, big_endian>
return strcmp(sym->name(), "___tls_get_addr") == 0;
}
+ // Return the PLT address to use for a global symbol.
+ uint64_t
+ do_plt_address_for_global(const Symbol* gsym) const
+ { return this->plt_section()->address_for_global(gsym); }
+
+ uint64_t
+ do_plt_address_for_local(const Relobj* relobj, unsigned int symndx) const
+ { return this->plt_section()->address_for_local(relobj, symndx); }
+
// Return whether there is a GOT section.
bool
has_got_section() const
@@ -176,6 +187,15 @@ class Target_sparc : public Sized_target<size, big_endian>
return this->got_size() / (size / 8);
}
+ // Return the address of the GOT.
+ uint64_t
+ got_address() const
+ {
+ if (this->got_ == NULL)
+ return 0;
+ return this->got_->address();
+ }
+
// Return the number of entries in the PLT.
unsigned int
plt_entry_count() const;
@@ -188,6 +208,15 @@ class Target_sparc : public Sized_target<size, big_endian>
unsigned int
plt_entry_size() const;
+ protected:
+ // Make an ELF object.
+ Object*
+ do_make_elf_object(const std::string&, Input_file*, off_t,
+ const elfcpp::Ehdr<size, big_endian>& ehdr);
+
+ void
+ do_adjust_elf_header(unsigned char* view, int len) const;
+
private:
// The class which scans relocations.
@@ -219,24 +248,24 @@ class Target_sparc : public Sized_target<size, big_endian>
inline bool
local_reloc_may_be_function_pointer(Symbol_table* , Layout* ,
- Target_sparc* ,
- Sized_relobj_file<size, big_endian>* ,
- unsigned int ,
- Output_section* ,
- const elfcpp::Rela<size, big_endian>& ,
+ Target_sparc* ,
+ Sized_relobj_file<size, big_endian>* ,
+ unsigned int ,
+ Output_section* ,
+ const elfcpp::Rela<size, big_endian>& ,
unsigned int ,
- const elfcpp::Sym<size, big_endian>&)
+ const elfcpp::Sym<size, big_endian>&)
{ return false; }
inline bool
global_reloc_may_be_function_pointer(Symbol_table* , Layout* ,
- Target_sparc* ,
- Sized_relobj_file<size, big_endian>* ,
- unsigned int ,
- Output_section* ,
- const elfcpp::Rela<size,
- big_endian>& ,
- unsigned int , Symbol*)
+ Target_sparc* ,
+ Sized_relobj_file<size, big_endian>* ,
+ unsigned int ,
+ Output_section* ,
+ const elfcpp::Rela<size,
+ big_endian>& ,
+ unsigned int , Symbol*)
{ return false; }
@@ -256,6 +285,10 @@ class Target_sparc : public Sized_target<size, big_endian>
void
check_non_pic(Relobj*, unsigned int r_type);
+ bool
+ reloc_needs_plt_for_ifunc(Sized_relobj_file<size, big_endian>*,
+ unsigned int r_type);
+
// Whether we have issued an error about a non-PIC compilation.
bool issued_non_pic_error_;
};
@@ -293,13 +326,19 @@ class Target_sparc : public Sized_target<size, big_endian>
// Do a TLS relocation.
inline void
relocate_tls(const Relocate_info<size, big_endian>*, Target_sparc* target,
- size_t relnum, const elfcpp::Rela<size, big_endian>&,
+ size_t relnum, const elfcpp::Rela<size, big_endian>&,
unsigned int r_type, const Sized_symbol<size>*,
const Symbol_value<size>*,
unsigned char*,
typename elfcpp::Elf_types<size>::Elf_Addr,
section_size_type);
+ inline void
+ relax_call(Target_sparc<size, big_endian>* target,
+ unsigned char* view,
+ const elfcpp::Rela<size, big_endian>& rela,
+ section_size_type view_size);
+
// Ignore the next relocation which should be R_SPARC_TLS_GD_ADD
bool ignore_gd_add_;
@@ -320,10 +359,20 @@ class Target_sparc : public Sized_target<size, big_endian>
Output_data_got<size, big_endian>*
got_section(Symbol_table*, Layout*);
+ // Create the PLT section.
+ void
+ make_plt_section(Symbol_table* symtab, Layout* layout);
+
// Create a PLT entry for a global symbol.
void
make_plt_entry(Symbol_table*, Layout*, Symbol*);
+ // Create a PLT entry for a local STT_GNU_IFUNC symbol.
+ void
+ make_local_ifunc_plt_entry(Symbol_table*, Layout*,
+ Sized_relobj_file<size, big_endian>* relobj,
+ unsigned int local_sym_index);
+
// Create a GOT entry for the TLS module index.
unsigned int
got_mod_index_entry(Symbol_table* symtab, Layout* layout,
@@ -341,7 +390,7 @@ class Target_sparc : public Sized_target<size, big_endian>
}
// Get the PLT section.
- const Output_data_plt_sparc<size, big_endian>*
+ Output_data_plt_sparc<size, big_endian>*
plt_section() const
{
gold_assert(this->plt_ != NULL);
@@ -352,10 +401,14 @@ class Target_sparc : public Sized_target<size, big_endian>
Reloc_section*
rela_dyn_section(Layout*);
+ // Get the section to use for IFUNC relocations.
+ Reloc_section*
+ rela_ifunc_section(Layout*);
+
// Copy a relocation against a global symbol.
void
copy_reloc(Symbol_table* symtab, Layout* layout,
- Sized_relobj_file<size, big_endian>* object,
+ Sized_relobj_file<size, big_endian>* object,
unsigned int shndx, Output_section* output_section,
Symbol* sym, const elfcpp::Rela<size, big_endian>& reloc)
{
@@ -386,6 +439,8 @@ class Target_sparc : public Sized_target<size, big_endian>
Output_data_plt_sparc<size, big_endian>* plt_;
// The dynamic reloc section.
Reloc_section* rela_dyn_;
+ // The section to use for IFUNC relocs.
+ Reloc_section* rela_ifunc_;
// Relocs saved to avoid a COPY reloc.
Copy_relocs<elfcpp::SHT_RELA, size, big_endian> copy_relocs_;
// Space for variables copied with a COPY reloc.
@@ -394,6 +449,12 @@ class Target_sparc : public Sized_target<size, big_endian>
unsigned int got_mod_index_offset_;
// Cached pointer to __tls_get_addr symbol
Symbol* tls_get_addr_sym_;
+ // Accumulated elf machine type
+ elfcpp::Elf_Half elf_machine_;
+ // Accumulated elf header flags
+ elfcpp::Elf_Word elf_flags_;
+ // Whether elf_flags_ has been set for the first time yet
+ bool elf_flags_set_;
};
template<>
@@ -412,6 +473,8 @@ Target::Target_info Target_sparc<32, true>::sparc_info =
0x00010000, // default_text_segment_address
64 * 1024, // abi_pagesize (overridable by -z max-page-size)
8 * 1024, // common_pagesize (overridable by -z common-page-size)
+ false, // isolate_execinstr
+ 0, // rosegment_gap
elfcpp::SHN_UNDEF, // small_common_shndx
elfcpp::SHN_UNDEF, // large_common_shndx
0, // small_common_section_flags
@@ -436,6 +499,8 @@ Target::Target_info Target_sparc<64, true>::sparc_info =
0x100000, // default_text_segment_address
64 * 1024, // abi_pagesize (overridable by -z max-page-size)
8 * 1024, // common_pagesize (overridable by -z common-page-size)
+ false, // isolate_execinstr
+ 0, // rosegment_gap
elfcpp::SHN_UNDEF, // small_common_shndx
elfcpp::SHN_UNDEF, // large_common_shndx
0, // small_common_section_flags
@@ -617,6 +682,29 @@ public:
elfcpp::Swap<32, true>::writeval(wv, val | reloc);
}
+ // R_SPARC_WDISP10: (Symbol + Addend - Address) >> 2
+ static inline void
+ wdisp10(unsigned char* view,
+ const Sized_relobj_file<size, big_endian>* object,
+ const Symbol_value<size>* psymval,
+ typename elfcpp::Elf_types<size>::Elf_Addr addend,
+ typename elfcpp::Elf_types<size>::Elf_Addr address)
+ {
+ typedef typename elfcpp::Swap<32, true>::Valtype Valtype;
+ Valtype* wv = reinterpret_cast<Valtype*>(view);
+ Valtype val = elfcpp::Swap<32, true>::readval(wv);
+ Valtype reloc = ((psymval->value(object, addend) - address)
+ >> 2);
+
+ // The relocation value is split between the low bits 5-12,
+ // and high bits 19-20.
+ val &= ~((0x3 << 19) | (0xff << 5));
+ reloc = (((reloc & 0x300) << (19 - 8))
+ | ((reloc & 0xff) << (5 - 0)));
+
+ elfcpp::Swap<32, true>::writeval(wv, val | reloc);
+ }
+
// R_SPARC_PC22: (Symbol + Addend - Address) >> 10
static inline void
pc22(unsigned char* view,
@@ -832,6 +920,16 @@ public:
addend, address);
}
+ // R_SPARC_H34: (Symbol + Addend) >> 12
+ static inline void
+ h34(unsigned char* view,
+ const Sized_relobj_file<size, big_endian>* object,
+ const Symbol_value<size>* psymval,
+ typename elfcpp::Elf_types<size>::Elf_Addr addend)
+ {
+ This_insn::template rela<32>(view, 12, 0x003fffff, object, psymval, addend);
+ }
+
// R_SPARC_H44: (Symbol + Addend) >> 22
static inline void
h44(unsigned char* view,
@@ -1003,6 +1101,28 @@ public:
elfcpp::Swap<32, true>::writeval(wv, val | reloc);
}
+ // R_SPARC_GOTDATA_OP_HIX22: @gdopoff(Symbol + Addend) >> 10
+ static inline void
+ gdop_hix22(unsigned char* view,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
+ typename elfcpp::Elf_types<size>::Elf_Addr addend)
+ {
+ typedef typename elfcpp::Swap<32, true>::Valtype Valtype;
+ Valtype* wv = reinterpret_cast<Valtype*>(view);
+ Valtype val = elfcpp::Swap<32, true>::readval(wv);
+ int32_t reloc = static_cast<int32_t>(value + addend);
+
+ val &= ~0x3fffff;
+
+ if (reloc < 0)
+ reloc ^= ~static_cast<int32_t>(0);
+ reloc >>= 10;
+
+ reloc &= 0x3fffff;
+
+ elfcpp::Swap<32, true>::writeval(wv, val | reloc);
+ }
+
// R_SPARC_HIX22: ((Symbol + Addend) ^ 0xffffffffffffffff) >> 10
static inline void
hix22(unsigned char* view,
@@ -1044,6 +1164,26 @@ public:
elfcpp::Swap<32, true>::writeval(wv, val | reloc);
}
+ // R_SPARC_GOTDATA_OP_LOX10: (@gdopoff(Symbol + Addend) & 0x3ff) | 0x1c00
+ static inline void
+ gdop_lox10(unsigned char* view,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
+ typename elfcpp::Elf_types<size>::Elf_Addr addend)
+ {
+ typedef typename elfcpp::Swap<32, true>::Valtype Valtype;
+ Valtype* wv = reinterpret_cast<Valtype*>(view);
+ Valtype val = elfcpp::Swap<32, true>::readval(wv);
+ int32_t reloc = static_cast<int32_t>(value + addend);
+
+ if (reloc < 0)
+ reloc = (reloc & 0x3ff) | 0x1c00;
+ else
+ reloc = (reloc & 0x3ff);
+
+ val &= ~0x1fff;
+ elfcpp::Swap<32, true>::writeval(wv, val | reloc);
+ }
+
// R_SPARC_LOX10: ((Symbol + Addend) & 0x3ff) | 0x1c00
static inline void
lox10(unsigned char* view,
@@ -1112,6 +1252,30 @@ Target_sparc<size, big_endian>::rela_dyn_section(Layout* layout)
return this->rela_dyn_;
}
+// Get the section to use for IFUNC relocs, creating it if
+// necessary. These go in .rela.dyn, but only after all other dynamic
+// relocations. They need to follow the other dynamic relocations so
+// that they can refer to global variables initialized by those
+// relocs.
+
+template<int size, bool big_endian>
+typename Target_sparc<size, big_endian>::Reloc_section*
+Target_sparc<size, big_endian>::rela_ifunc_section(Layout* layout)
+{
+ if (this->rela_ifunc_ == NULL)
+ {
+ // Make sure we have already created the dynamic reloc section.
+ this->rela_dyn_section(layout);
+ this->rela_ifunc_ = new Reloc_section(false);
+ layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
+ elfcpp::SHF_ALLOC, this->rela_ifunc_,
+ ORDER_DYNAMIC_RELOCS, false);
+ gold_assert(this->rela_dyn_->output_section()
+ == this->rela_ifunc_->output_section());
+ }
+ return this->rela_ifunc_;
+}
+
// A class to handle the PLT data.
template<int size, bool big_endian>
@@ -1124,7 +1288,13 @@ class Output_data_plt_sparc : public Output_section_data
Output_data_plt_sparc(Layout*);
// Add an entry to the PLT.
- void add_entry(Symbol* gsym);
+ void add_entry(Symbol_table* symtab, Layout* layout, Symbol* gsym);
+
+ // Add an entry to the PLT for a local STT_GNU_IFUNC symbol.
+ unsigned int
+ add_local_ifunc_entry(Symbol_table*, Layout*,
+ Sized_relobj_file<size, big_endian>* relobj,
+ unsigned int local_sym_index);
// Return the .rela.plt section data.
const Reloc_section* rel_plt() const
@@ -1132,10 +1302,22 @@ class Output_data_plt_sparc : public Output_section_data
return this->rel_;
}
+ // Return where the IFUNC relocations should go.
+ Reloc_section*
+ rela_ifunc(Symbol_table*, Layout*);
+
+ void
+ emit_pending_ifunc_relocs();
+
+ // Return whether we created a section for IFUNC relocations.
+ bool
+ has_ifunc_section() const
+ { return this->ifunc_rel_ != NULL; }
+
// Return the number of PLT entries.
unsigned int
entry_count() const
- { return this->count_; }
+ { return this->count_ + this->ifunc_count_; }
// Return the offset of the first non-reserved PLT entry.
static unsigned int
@@ -1147,6 +1329,14 @@ class Output_data_plt_sparc : public Output_section_data
get_plt_entry_size()
{ return base_plt_entry_size; }
+ // Return the PLT address to use for a global symbol.
+ uint64_t
+ address_for_global(const Symbol*);
+
+ // Return the PLT address to use for a local symbol.
+ uint64_t
+ address_for_local(const Relobj*, unsigned int symndx);
+
protected:
void do_adjust_output_section(Output_section* os);
@@ -1166,34 +1356,69 @@ class Output_data_plt_sparc : public Output_section_data
(plt_entries_per_block
* (plt_insn_chunk_size + plt_pointer_chunk_size));
- // Set the final size.
- void
- set_final_data_size()
+ section_offset_type
+ plt_index_to_offset(unsigned int index)
{
- unsigned int full_count = this->count_ + 4;
- unsigned int extra = (size == 32 ? 4 : 0);
+ section_offset_type offset;
- if (size == 32 || full_count < 32768)
- this->set_data_size((full_count * base_plt_entry_size) + extra);
+ if (size == 32 || index < 32768)
+ offset = index * base_plt_entry_size;
else
{
- unsigned int ext_cnt = full_count - 32768;
+ unsigned int ext_index = index - 32768;
- this->set_data_size((32768 * base_plt_entry_size)
- + (ext_cnt
- * (plt_insn_chunk_size
- + plt_pointer_chunk_size)));
+ offset = (32768 * base_plt_entry_size)
+ + ((ext_index / plt_entries_per_block)
+ * plt_block_size)
+ + ((ext_index % plt_entries_per_block)
+ * plt_insn_chunk_size);
}
+ return offset;
+ }
+
+ // Set the final size.
+ void
+ set_final_data_size()
+ {
+ unsigned int full_count = this->entry_count() + 4;
+ unsigned int extra = (size == 32 ? 4 : 0);
+ section_offset_type sz = plt_index_to_offset(full_count) + extra;
+
+ return this->set_data_size(sz);
}
// Write out the PLT data.
void
do_write(Output_file*);
+ struct Global_ifunc
+ {
+ Reloc_section* rel;
+ Symbol* gsym;
+ unsigned int plt_index;
+ };
+
+ struct Local_ifunc
+ {
+ Reloc_section* rel;
+ Sized_relobj_file<size, big_endian>* object;
+ unsigned int local_sym_index;
+ unsigned int plt_index;
+ };
+
// The reloc section.
Reloc_section* rel_;
+ // The IFUNC relocations, if necessary. These must follow the
+ // regular relocations.
+ Reloc_section* ifunc_rel_;
// The number of PLT entries.
unsigned int count_;
+ // The number of PLT entries for IFUNC symbols.
+ unsigned int ifunc_count_;
+ // Global STT_GNU_IFUNC symbols.
+ std::vector<Global_ifunc> global_ifuncs_;
+ // Local STT_GNU_IFUNC symbols.
+ std::vector<Local_ifunc> local_ifuncs_;
};
// Define the constants as required by C++ standard.
@@ -1220,7 +1445,8 @@ const unsigned int Output_data_plt_sparc<size, big_endian>::plt_block_size;
template<int size, bool big_endian>
Output_data_plt_sparc<size, big_endian>::Output_data_plt_sparc(Layout* layout)
- : Output_section_data(size == 32 ? 4 : 8), count_(0)
+ : Output_section_data(size == 32 ? 4 : 8), ifunc_rel_(NULL),
+ count_(0), ifunc_count_(0), global_ifuncs_(), local_ifuncs_()
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
@@ -1239,38 +1465,171 @@ Output_data_plt_sparc<size, big_endian>::do_adjust_output_section(Output_section
template<int size, bool big_endian>
void
-Output_data_plt_sparc<size, big_endian>::add_entry(Symbol* gsym)
+Output_data_plt_sparc<size, big_endian>::add_entry(Symbol_table* symtab,
+ Layout* layout,
+ Symbol* gsym)
{
gold_assert(!gsym->has_plt_offset());
- unsigned int index = this->count_ + 4;
section_offset_type plt_offset;
+ unsigned int index;
- if (size == 32 || index < 32768)
- plt_offset = index * base_plt_entry_size;
+ if (gsym->type() == elfcpp::STT_GNU_IFUNC
+ && gsym->can_use_relative_reloc(false))
+ {
+ index = this->ifunc_count_;
+ plt_offset = plt_index_to_offset(index);
+ gsym->set_plt_offset(plt_offset);
+ ++this->ifunc_count_;
+ Reloc_section* rel = this->rela_ifunc(symtab, layout);
+
+ struct Global_ifunc gi;
+ gi.rel = rel;
+ gi.gsym = gsym;
+ gi.plt_index = index;
+ this->global_ifuncs_.push_back(gi);
+ }
else
{
- unsigned int ext_index = index - 32768;
+ plt_offset = plt_index_to_offset(this->count_ + 4);
+ gsym->set_plt_offset(plt_offset);
+ ++this->count_;
+ gsym->set_needs_dynsym_entry();
+ this->rel_->add_global(gsym, elfcpp::R_SPARC_JMP_SLOT, this,
+ plt_offset, 0);
+ }
- plt_offset = (32768 * base_plt_entry_size)
- + ((ext_index / plt_entries_per_block)
- * plt_block_size)
- + ((ext_index % plt_entries_per_block)
- * plt_insn_chunk_size);
+ // Note that we don't need to save the symbol. The contents of the
+ // PLT are independent of which symbols are used. The symbols only
+ // appear in the relocations.
+}
+
+template<int size, bool big_endian>
+unsigned int
+Output_data_plt_sparc<size, big_endian>::add_local_ifunc_entry(
+ Symbol_table* symtab,
+ Layout* layout,
+ Sized_relobj_file<size, big_endian>* relobj,
+ unsigned int local_sym_index)
+{
+ unsigned int index = this->ifunc_count_;
+ section_offset_type plt_offset;
+
+ plt_offset = plt_index_to_offset(index);
+ ++this->ifunc_count_;
+
+ Reloc_section* rel = this->rela_ifunc(symtab, layout);
+
+ struct Local_ifunc li;
+ li.rel = rel;
+ li.object = relobj;
+ li.local_sym_index = local_sym_index;
+ li.plt_index = index;
+ this->local_ifuncs_.push_back(li);
+
+ return plt_offset;
+}
+
+// Emit any pending IFUNC plt relocations.
+
+template<int size, bool big_endian>
+void
+Output_data_plt_sparc<size, big_endian>::emit_pending_ifunc_relocs()
+{
+ // Emit any pending IFUNC relocs.
+ for (typename std::vector<Global_ifunc>::const_iterator p =
+ this->global_ifuncs_.begin();
+ p != this->global_ifuncs_.end();
+ ++p)
+ {
+ section_offset_type plt_offset;
+ unsigned int index;
+
+ index = this->count_ + p->plt_index + 4;
+ plt_offset = this->plt_index_to_offset(index);
+ p->rel->add_symbolless_global_addend(p->gsym, elfcpp::R_SPARC_JMP_IREL,
+ this, plt_offset, 0);
}
- gsym->set_plt_offset(plt_offset);
+ for (typename std::vector<Local_ifunc>::const_iterator p =
+ this->local_ifuncs_.begin();
+ p != this->local_ifuncs_.end();
+ ++p)
+ {
+ section_offset_type plt_offset;
+ unsigned int index;
+
+ index = this->count_ + p->plt_index + 4;
+ plt_offset = this->plt_index_to_offset(index);
+ p->rel->add_symbolless_local_addend(p->object, p->local_sym_index,
+ elfcpp::R_SPARC_JMP_IREL,
+ this, plt_offset, 0);
+ }
+}
- ++this->count_;
+// Return where the IFUNC relocations should go in the PLT. These
+// follow the non-IFUNC relocations.
- // Every PLT entry needs a reloc.
- gsym->set_needs_dynsym_entry();
- this->rel_->add_global(gsym, elfcpp::R_SPARC_JMP_SLOT, this,
- plt_offset, 0);
+template<int size, bool big_endian>
+typename Output_data_plt_sparc<size, big_endian>::Reloc_section*
+Output_data_plt_sparc<size, big_endian>::rela_ifunc(
+ Symbol_table* symtab,
+ Layout* layout)
+{
+ if (this->ifunc_rel_ == NULL)
+ {
+ this->ifunc_rel_ = new Reloc_section(false);
+ layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
+ elfcpp::SHF_ALLOC, this->ifunc_rel_,
+ ORDER_DYNAMIC_PLT_RELOCS, false);
+ gold_assert(this->ifunc_rel_->output_section()
+ == this->rel_->output_section());
+
+ if (parameters->doing_static_link())
+ {
+ // A statically linked executable will only have a .rel.plt
+ // section to hold R_SPARC_IRELATIVE and R_SPARC_JMP_IREL
+ // relocs for STT_GNU_IFUNC symbols. The library will use
+ // these symbols to locate the IRELATIVE and JMP_IREL relocs
+ // at program startup time.
+ symtab->define_in_output_data("__rela_iplt_start", NULL,
+ Symbol_table::PREDEFINED,
+ this->ifunc_rel_, 0, 0,
+ elfcpp::STT_NOTYPE, elfcpp::STB_GLOBAL,
+ elfcpp::STV_HIDDEN, 0, false, true);
+ symtab->define_in_output_data("__rela_iplt_end", NULL,
+ Symbol_table::PREDEFINED,
+ this->ifunc_rel_, 0, 0,
+ elfcpp::STT_NOTYPE, elfcpp::STB_GLOBAL,
+ elfcpp::STV_HIDDEN, 0, true, true);
+ }
+ }
+ return this->ifunc_rel_;
+}
- // Note that we don't need to save the symbol. The contents of the
- // PLT are independent of which symbols are used. The symbols only
- // appear in the relocations.
+// Return the PLT address to use for a global symbol.
+
+template<int size, bool big_endian>
+uint64_t
+Output_data_plt_sparc<size, big_endian>::address_for_global(const Symbol* gsym)
+{
+ uint64_t offset = 0;
+ if (gsym->type() == elfcpp::STT_GNU_IFUNC
+ && gsym->can_use_relative_reloc(false))
+ offset = plt_index_to_offset(this->count_ + 4);
+ return this->address() + offset;
+}
+
+// Return the PLT address to use for a local symbol. These are always
+// IRELATIVE relocs.
+
+template<int size, bool big_endian>
+uint64_t
+Output_data_plt_sparc<size, big_endian>::address_for_local(
+ const Relobj*,
+ unsigned int)
+{
+ return this->address() + plt_index_to_offset(this->count_ + 4);
}
static const unsigned int sparc_nop = 0x01000000;
@@ -1298,10 +1657,10 @@ Output_data_plt_sparc<size, big_endian>::do_write(Output_file* of)
unsigned char* pov = oview;
memset(pov, 0, base_plt_entry_size * 4);
- pov += base_plt_entry_size * 4;
+ pov += this->first_plt_entry_offset();
unsigned int plt_offset = base_plt_entry_size * 4;
- const unsigned int count = this->count_;
+ const unsigned int count = this->entry_count();
if (size == 64)
{
@@ -1421,6 +1780,38 @@ Output_data_plt_sparc<size, big_endian>::do_write(Output_file* of)
of->write_output_view(offset, oview_size, oview);
}
+// Create the PLT section.
+
+template<int size, bool big_endian>
+void
+Target_sparc<size, big_endian>::make_plt_section(Symbol_table* symtab,
+ Layout* layout)
+{
+ // Create the GOT sections first.
+ this->got_section(symtab, layout);
+
+ // Ensure that .rela.dyn always appears before .rela.plt This is
+ // necessary due to how, on Sparc and some other targets, .rela.dyn
+ // needs to include .rela.plt in it's range.
+ this->rela_dyn_section(layout);
+
+ this->plt_ = new Output_data_plt_sparc<size, big_endian>(layout);
+ layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
+ (elfcpp::SHF_ALLOC
+ | elfcpp::SHF_EXECINSTR
+ | elfcpp::SHF_WRITE),
+ this->plt_, ORDER_NON_RELRO_FIRST, false);
+
+ // Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section.
+ symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL,
+ Symbol_table::PREDEFINED,
+ this->plt_,
+ 0, 0, elfcpp::STT_OBJECT,
+ elfcpp::STB_LOCAL,
+ elfcpp::STV_HIDDEN, 0,
+ false, false);
+}
+
// Create a PLT entry for a global symbol.
template<int size, bool big_endian>
@@ -1433,33 +1824,29 @@ Target_sparc<size, big_endian>::make_plt_entry(Symbol_table* symtab,
return;
if (this->plt_ == NULL)
- {
- // Create the GOT sections first.
- this->got_section(symtab, layout);
+ this->make_plt_section(symtab, layout);
- // Ensure that .rela.dyn always appears before .rela.plt This is
- // necessary due to how, on Sparc and some other targets, .rela.dyn
- // needs to include .rela.plt in it's range.
- this->rela_dyn_section(layout);
-
- this->plt_ = new Output_data_plt_sparc<size, big_endian>(layout);
- layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
- (elfcpp::SHF_ALLOC
- | elfcpp::SHF_EXECINSTR
- | elfcpp::SHF_WRITE),
- this->plt_, ORDER_PLT, false);
+ this->plt_->add_entry(symtab, layout, gsym);
+}
- // Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section.
- symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL,
- Symbol_table::PREDEFINED,
- this->plt_,
- 0, 0, elfcpp::STT_OBJECT,
- elfcpp::STB_LOCAL,
- elfcpp::STV_HIDDEN, 0,
- false, false);
- }
+// Make a PLT entry for a local STT_GNU_IFUNC symbol.
- this->plt_->add_entry(gsym);
+template<int size, bool big_endian>
+void
+Target_sparc<size, big_endian>::make_local_ifunc_plt_entry(
+ Symbol_table* symtab,
+ Layout* layout,
+ Sized_relobj_file<size, big_endian>* relobj,
+ unsigned int local_sym_index)
+{
+ if (relobj->local_has_plt_offset(local_sym_index))
+ return;
+ if (this->plt_ == NULL)
+ this->make_plt_section(symtab, layout);
+ unsigned int plt_offset = this->plt_->add_local_ifunc_entry(symtab, layout,
+ relobj,
+ local_sym_index);
+ relobj->set_local_plt_offset(local_sym_index, plt_offset);
}
// Return the number of entries in the PLT.
@@ -1605,6 +1992,7 @@ Target_sparc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
case elfcpp::R_SPARC_64:
case elfcpp::R_SPARC_HIX22:
case elfcpp::R_SPARC_LOX10:
+ case elfcpp::R_SPARC_H34:
case elfcpp::R_SPARC_H44:
case elfcpp::R_SPARC_M44:
case elfcpp::R_SPARC_L44:
@@ -1639,6 +2027,7 @@ Target_sparc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
case elfcpp::R_SPARC_WDISP22:
case elfcpp::R_SPARC_WDISP19:
case elfcpp::R_SPARC_WDISP16:
+ case elfcpp::R_SPARC_WDISP10:
return Symbol::RELATIVE_REF;
case elfcpp::R_SPARC_PLT64:
@@ -1685,7 +2074,9 @@ Target_sparc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
case elfcpp::R_SPARC_COPY:
case elfcpp::R_SPARC_GLOB_DAT:
case elfcpp::R_SPARC_JMP_SLOT:
+ case elfcpp::R_SPARC_JMP_IREL:
case elfcpp::R_SPARC_RELATIVE:
+ case elfcpp::R_SPARC_IRELATIVE:
case elfcpp::R_SPARC_TLS_DTPMOD64:
case elfcpp::R_SPARC_TLS_DTPMOD32:
case elfcpp::R_SPARC_TLS_DTPOFF64:
@@ -1737,10 +2128,12 @@ Target_sparc<size, big_endian>::Scan::check_non_pic(Relobj* object, unsigned int
{
// These are the relocation types supported by glibc for sparc 64-bit.
case elfcpp::R_SPARC_RELATIVE:
+ case elfcpp::R_SPARC_IRELATIVE:
case elfcpp::R_SPARC_COPY:
case elfcpp::R_SPARC_64:
case elfcpp::R_SPARC_GLOB_DAT:
case elfcpp::R_SPARC_JMP_SLOT:
+ case elfcpp::R_SPARC_JMP_IREL:
case elfcpp::R_SPARC_TLS_DTPMOD64:
case elfcpp::R_SPARC_TLS_DTPOFF64:
case elfcpp::R_SPARC_TLS_TPOFF64:
@@ -1755,6 +2148,7 @@ Target_sparc<size, big_endian>::Scan::check_non_pic(Relobj* object, unsigned int
case elfcpp::R_SPARC_LO10:
case elfcpp::R_SPARC_HI22:
case elfcpp::R_SPARC_OLO10:
+ case elfcpp::R_SPARC_H34:
case elfcpp::R_SPARC_H44:
case elfcpp::R_SPARC_M44:
case elfcpp::R_SPARC_L44:
@@ -1776,10 +2170,12 @@ Target_sparc<size, big_endian>::Scan::check_non_pic(Relobj* object, unsigned int
{
// These are the relocation types supported by glibc for sparc 32-bit.
case elfcpp::R_SPARC_RELATIVE:
+ case elfcpp::R_SPARC_IRELATIVE:
case elfcpp::R_SPARC_COPY:
case elfcpp::R_SPARC_GLOB_DAT:
case elfcpp::R_SPARC_32:
case elfcpp::R_SPARC_JMP_SLOT:
+ case elfcpp::R_SPARC_JMP_IREL:
case elfcpp::R_SPARC_TLS_DTPMOD32:
case elfcpp::R_SPARC_TLS_DTPOFF32:
case elfcpp::R_SPARC_TLS_TPOFF32:
@@ -1814,6 +2210,22 @@ Target_sparc<size, big_endian>::Scan::check_non_pic(Relobj* object, unsigned int
return;
}
+// Return whether we need to make a PLT entry for a relocation of the
+// given type against a STT_GNU_IFUNC symbol.
+
+template<int size, bool big_endian>
+bool
+Target_sparc<size, big_endian>::Scan::reloc_needs_plt_for_ifunc(
+ Sized_relobj_file<size, big_endian>* object,
+ unsigned int r_type)
+{
+ int flags = Scan::get_reference_flags(r_type);
+ if (flags & Symbol::TLS_REF)
+ gold_error(_("%s: unsupported TLS reloc %u for IFUNC symbol"),
+ object->name().c_str(), r_type);
+ return flags != 0;
+}
+
// Scan a relocation for a local symbol.
template<int size, bool big_endian>
@@ -1829,9 +2241,17 @@ Target_sparc<size, big_endian>::Scan::local(
unsigned int r_type,
const elfcpp::Sym<size, big_endian>& lsym)
{
+ bool is_ifunc = lsym.get_st_type() == elfcpp::STT_GNU_IFUNC;
unsigned int orig_r_type = r_type;
-
r_type &= 0xff;
+
+ if (is_ifunc
+ && this->reloc_needs_plt_for_ifunc(object, r_type))
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+ target->make_local_ifunc_plt_entry(symtab, layout, object, r_sym);
+ }
+
switch (r_type)
{
case elfcpp::R_SPARC_NONE:
@@ -1849,18 +2269,19 @@ Target_sparc<size, big_endian>::Scan::local(
// an R_SPARC_RELATIVE relocation so the dynamic loader can
// relocate it easily.
if (parameters->options().output_is_position_independent())
- {
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
- rela_dyn->add_local_relative(object, r_sym, elfcpp::R_SPARC_RELATIVE,
+ {
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+ rela_dyn->add_local_relative(object, r_sym, elfcpp::R_SPARC_RELATIVE,
output_section, data_shndx,
reloc.get_r_offset(),
- reloc.get_r_addend());
- }
+ reloc.get_r_addend(), is_ifunc);
+ }
break;
case elfcpp::R_SPARC_HIX22:
case elfcpp::R_SPARC_LOX10:
+ case elfcpp::R_SPARC_H34:
case elfcpp::R_SPARC_H44:
case elfcpp::R_SPARC_M44:
case elfcpp::R_SPARC_L44:
@@ -1884,26 +2305,26 @@ Target_sparc<size, big_endian>::Scan::local(
// executable), we need to create a dynamic relocation for
// this location.
if (parameters->options().output_is_position_independent())
- {
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+ {
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
check_non_pic(object, r_type);
- if (lsym.get_st_type() != elfcpp::STT_SECTION)
- {
- rela_dyn->add_local(object, r_sym, orig_r_type, output_section,
+ if (lsym.get_st_type() != elfcpp::STT_SECTION)
+ {
+ rela_dyn->add_local(object, r_sym, orig_r_type, output_section,
data_shndx, reloc.get_r_offset(),
reloc.get_r_addend());
- }
- else
- {
- gold_assert(lsym.get_st_value() == 0);
+ }
+ else
+ {
+ gold_assert(lsym.get_st_value() == 0);
rela_dyn->add_symbolless_local_addend(object, r_sym, orig_r_type,
output_section, data_shndx,
reloc.get_r_offset(),
reloc.get_r_addend());
- }
- }
+ }
+ }
break;
case elfcpp::R_SPARC_WDISP30:
@@ -1911,6 +2332,7 @@ Target_sparc<size, big_endian>::Scan::local(
case elfcpp::R_SPARC_WDISP22:
case elfcpp::R_SPARC_WDISP19:
case elfcpp::R_SPARC_WDISP16:
+ case elfcpp::R_SPARC_WDISP10:
case elfcpp::R_SPARC_DISP8:
case elfcpp::R_SPARC_DISP16:
case elfcpp::R_SPARC_DISP32:
@@ -1922,13 +2344,17 @@ Target_sparc<size, big_endian>::Scan::local(
case elfcpp::R_SPARC_GOTDATA_OP:
case elfcpp::R_SPARC_GOTDATA_OP_HIX22:
case elfcpp::R_SPARC_GOTDATA_OP_LOX10:
+ // We will optimize this into a GOT relative relocation
+ // and code transform the GOT load into an addition.
+ break;
+
case elfcpp::R_SPARC_GOT10:
case elfcpp::R_SPARC_GOT13:
case elfcpp::R_SPARC_GOT22:
{
- // The symbol requires a GOT entry.
- Output_data_got<size, big_endian>* got;
- unsigned int r_sym;
+ // The symbol requires a GOT entry.
+ Output_data_got<size, big_endian>* got;
+ unsigned int r_sym;
got = target->got_section(symtab, layout);
r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
@@ -1940,13 +2366,11 @@ Target_sparc<size, big_endian>::Scan::local(
if (!object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD))
{
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- unsigned int off;
-
- off = got->add_constant(0);
+ unsigned int off = got->add_constant(0);
object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off);
rela_dyn->add_local_relative(object, r_sym,
elfcpp::R_SPARC_RELATIVE,
- got, off, 0);
+ got, off, 0, is_ifunc);
}
}
else
@@ -1977,7 +2401,7 @@ Target_sparc<size, big_endian>::Scan::local(
{
bool output_is_shared = parameters->options().shared();
const tls::Tls_optimization optimized_type
- = optimize_tls_reloc(!output_is_shared, r_type);
+ = optimize_tls_reloc(!output_is_shared, r_type);
switch (r_type)
{
case elfcpp::R_SPARC_TLS_GD_HI22: // Global-dynamic
@@ -1986,11 +2410,11 @@ Target_sparc<size, big_endian>::Scan::local(
case elfcpp::R_SPARC_TLS_GD_CALL:
if (optimized_type == tls::TLSOPT_NONE)
{
- // Create a pair of GOT entries for the module index and
- // dtv-relative offset.
- Output_data_got<size, big_endian>* got
- = target->got_section(symtab, layout);
- unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+ // Create a pair of GOT entries for the module index and
+ // dtv-relative offset.
+ Output_data_got<size, big_endian>* got
+ = target->got_section(symtab, layout);
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
unsigned int shndx = lsym.get_st_shndx();
bool is_ordinary;
shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
@@ -1998,14 +2422,14 @@ Target_sparc<size, big_endian>::Scan::local(
object->error(_("local symbol %u has bad shndx %u"),
r_sym, shndx);
else
- got->add_local_pair_with_rela(object, r_sym,
- lsym.get_st_shndx(),
- GOT_TYPE_TLS_PAIR,
- target->rela_dyn_section(layout),
- (size == 64
- ? elfcpp::R_SPARC_TLS_DTPMOD64
- : elfcpp::R_SPARC_TLS_DTPMOD32),
- 0);
+ got->add_local_pair_with_rel(object, r_sym,
+ lsym.get_st_shndx(),
+ GOT_TYPE_TLS_PAIR,
+ target->rela_dyn_section(layout),
+ (size == 64
+ ? elfcpp::R_SPARC_TLS_DTPMOD64
+ : elfcpp::R_SPARC_TLS_DTPMOD32),
+ 0);
if (r_type == elfcpp::R_SPARC_TLS_GD_CALL)
generate_tls_call(symtab, layout, target);
}
@@ -2070,11 +2494,11 @@ Target_sparc<size, big_endian>::Scan::local(
layout->set_has_static_tls();
if (output_is_shared)
{
- // We need to create a dynamic relocation.
- gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
- unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- rela_dyn->add_symbolless_local_addend(object, r_sym, r_type,
+ // We need to create a dynamic relocation.
+ gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ rela_dyn->add_symbolless_local_addend(object, r_sym, r_type,
output_section, data_shndx,
reloc.get_r_offset(), 0);
}
@@ -2088,7 +2512,9 @@ Target_sparc<size, big_endian>::Scan::local(
case elfcpp::R_SPARC_COPY:
case elfcpp::R_SPARC_GLOB_DAT:
case elfcpp::R_SPARC_JMP_SLOT:
+ case elfcpp::R_SPARC_JMP_IREL:
case elfcpp::R_SPARC_RELATIVE:
+ case elfcpp::R_SPARC_IRELATIVE:
case elfcpp::R_SPARC_TLS_DTPMOD64:
case elfcpp::R_SPARC_TLS_DTPMOD32:
case elfcpp::R_SPARC_TLS_DTPOFF64:
@@ -2134,6 +2560,7 @@ Target_sparc<size, big_endian>::Scan::global(
Symbol* gsym)
{
unsigned int orig_r_type = r_type;
+ bool is_ifunc = gsym->type() == elfcpp::STT_GNU_IFUNC;
// A reference to _GLOBAL_OFFSET_TABLE_ implies that we need a got
// section. We check here to avoid creating a dynamic reloc against
@@ -2143,6 +2570,12 @@ Target_sparc<size, big_endian>::Scan::global(
target->got_section(symtab, layout);
r_type &= 0xff;
+
+ // A STT_GNU_IFUNC symbol may require a PLT entry.
+ if (is_ifunc
+ && this->reloc_needs_plt_for_ifunc(object, r_type))
+ target->make_plt_entry(symtab, layout, gsym);
+
switch (r_type)
{
case elfcpp::R_SPARC_NONE:
@@ -2167,8 +2600,8 @@ Target_sparc<size, big_endian>::Scan::global(
// if the symbol is defined in the output file and is protected
// or hidden.
if (gsym->is_defined()
- && !gsym->is_from_dynobj()
- && !gsym->is_preemptible())
+ && !gsym->is_from_dynobj()
+ && !gsym->is_preemptible())
break;
target->make_plt_entry(symtab, layout, gsym);
break;
@@ -2186,6 +2619,7 @@ Target_sparc<size, big_endian>::Scan::global(
case elfcpp::R_SPARC_WDISP22:
case elfcpp::R_SPARC_WDISP19:
case elfcpp::R_SPARC_WDISP16:
+ case elfcpp::R_SPARC_WDISP10:
{
if (gsym->needs_plt_entry())
target->make_plt_entry(symtab, layout, gsym);
@@ -2214,6 +2648,7 @@ Target_sparc<size, big_endian>::Scan::global(
case elfcpp::R_SPARC_64:
case elfcpp::R_SPARC_HIX22:
case elfcpp::R_SPARC_LOX10:
+ case elfcpp::R_SPARC_H34:
case elfcpp::R_SPARC_H44:
case elfcpp::R_SPARC_M44:
case elfcpp::R_SPARC_L44:
@@ -2234,24 +2669,24 @@ Target_sparc<size, big_endian>::Scan::global(
case elfcpp::R_SPARC_6:
case elfcpp::R_SPARC_5:
{
- // Make a PLT entry if necessary.
- if (gsym->needs_plt_entry())
- {
- target->make_plt_entry(symtab, layout, gsym);
- // Since this is not a PC-relative relocation, we may be
- // taking the address of a function. In that case we need to
- // set the entry in the dynamic symbol table to the address of
- // the PLT entry.
- if (gsym->is_from_dynobj() && !parameters->options().shared())
- gsym->set_needs_dynsym_value();
- }
- // Make a dynamic relocation if necessary.
- if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
- {
+ // Make a PLT entry if necessary.
+ if (gsym->needs_plt_entry())
+ {
+ target->make_plt_entry(symtab, layout, gsym);
+ // Since this is not a PC-relative relocation, we may be
+ // taking the address of a function. In that case we need to
+ // set the entry in the dynamic symbol table to the address of
+ // the PLT entry.
+ if (gsym->is_from_dynobj() && !parameters->options().shared())
+ gsym->set_needs_dynsym_value();
+ }
+ // Make a dynamic relocation if necessary.
+ if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
+ {
unsigned int r_off = reloc.get_r_offset();
// The assembler can sometimes emit unaligned relocations
- // for dwarf2 cfi directives.
+ // for dwarf2 cfi directives.
switch (r_type)
{
case elfcpp::R_SPARC_16:
@@ -2280,24 +2715,45 @@ Target_sparc<size, big_endian>::Scan::global(
break;
}
- if (gsym->may_need_copy_reloc())
- {
- target->copy_reloc(symtab, layout, object,
- data_shndx, output_section, gsym, reloc);
- }
- else if ((r_type == elfcpp::R_SPARC_32
+ if (gsym->may_need_copy_reloc())
+ {
+ target->copy_reloc(symtab, layout, object,
+ data_shndx, output_section, gsym, reloc);
+ }
+ else if (((size == 64 && r_type == elfcpp::R_SPARC_64)
+ || (size == 32 && r_type == elfcpp::R_SPARC_32))
+ && gsym->type() == elfcpp::STT_GNU_IFUNC
+ && gsym->can_use_relative_reloc(false)
+ && !gsym->is_from_dynobj()
+ && !gsym->is_undefined()
+ && !gsym->is_preemptible())
+ {
+ // Use an IRELATIVE reloc for a locally defined
+ // STT_GNU_IFUNC symbol. This makes a function
+ // address in a PIE executable match the address in a
+ // shared library that it links against.
+ Reloc_section* rela_dyn =
+ target->rela_ifunc_section(layout);
+ unsigned int r_type = elfcpp::R_SPARC_IRELATIVE;
+ rela_dyn->add_symbolless_global_addend(gsym, r_type,
+ output_section, object,
+ data_shndx,
+ reloc.get_r_offset(),
+ reloc.get_r_addend());
+ }
+ else if ((r_type == elfcpp::R_SPARC_32
|| r_type == elfcpp::R_SPARC_64)
- && gsym->can_use_relative_reloc(false))
- {
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- rela_dyn->add_global_relative(gsym, elfcpp::R_SPARC_RELATIVE,
+ && gsym->can_use_relative_reloc(false))
+ {
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ rela_dyn->add_global_relative(gsym, elfcpp::R_SPARC_RELATIVE,
output_section, object,
data_shndx, reloc.get_r_offset(),
- reloc.get_r_addend());
- }
- else
- {
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ reloc.get_r_addend(), is_ifunc);
+ }
+ else
+ {
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
check_non_pic(object, r_type);
if (gsym->is_from_dynobj()
@@ -2313,43 +2769,96 @@ Target_sparc<size, big_endian>::Scan::global(
object, data_shndx,
reloc.get_r_offset(),
reloc.get_r_addend());
- }
- }
+ }
+ }
}
break;
case elfcpp::R_SPARC_GOTDATA_OP:
case elfcpp::R_SPARC_GOTDATA_OP_HIX22:
case elfcpp::R_SPARC_GOTDATA_OP_LOX10:
+ if (gsym->is_defined()
+ && !gsym->is_from_dynobj()
+ && !gsym->is_preemptible()
+ && !is_ifunc)
+ {
+ // We will optimize this into a GOT relative relocation
+ // and code transform the GOT load into an addition.
+ break;
+ }
case elfcpp::R_SPARC_GOT10:
case elfcpp::R_SPARC_GOT13:
case elfcpp::R_SPARC_GOT22:
{
- // The symbol requires a GOT entry.
- Output_data_got<size, big_endian>* got;
+ // The symbol requires a GOT entry.
+ Output_data_got<size, big_endian>* got;
got = target->got_section(symtab, layout);
- if (gsym->final_value_is_known())
- got->add_global(gsym, GOT_TYPE_STANDARD);
- else
- {
- // If this symbol is not fully resolved, we need to add a
- // dynamic relocation for it.
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- if (gsym->is_from_dynobj()
- || gsym->is_undefined()
- || gsym->is_preemptible())
- got->add_global_with_rela(gsym, GOT_TYPE_STANDARD, rela_dyn,
- elfcpp::R_SPARC_GLOB_DAT);
- else if (!gsym->has_got_offset(GOT_TYPE_STANDARD))
- {
+ if (gsym->final_value_is_known())
+ {
+ // For a STT_GNU_IFUNC symbol we want the PLT address.
+ if (gsym->type() == elfcpp::STT_GNU_IFUNC)
+ got->add_global_plt(gsym, GOT_TYPE_STANDARD);
+ else
+ got->add_global(gsym, GOT_TYPE_STANDARD);
+ }
+ else
+ {
+ // If this symbol is not fully resolved, we need to add a
+ // GOT entry with a dynamic relocation.
+ bool is_ifunc = gsym->type() == elfcpp::STT_GNU_IFUNC;
+
+ // Use a GLOB_DAT rather than a RELATIVE reloc if:
+ //
+ // 1) The symbol may be defined in some other module.
+ //
+ // 2) We are building a shared library and this is a
+ // protected symbol; using GLOB_DAT means that the dynamic
+ // linker can use the address of the PLT in the main
+ // executable when appropriate so that function address
+ // comparisons work.
+ //
+ // 3) This is a STT_GNU_IFUNC symbol in position dependent
+ // code, again so that function address comparisons work.
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ if (gsym->is_from_dynobj()
+ || gsym->is_undefined()
+ || gsym->is_preemptible()
+ || (gsym->visibility() == elfcpp::STV_PROTECTED
+ && parameters->options().shared())
+ || (gsym->type() == elfcpp::STT_GNU_IFUNC
+ && parameters->options().output_is_position_independent()
+ && !gsym->is_forced_local()))
+ {
+ unsigned int r_type = elfcpp::R_SPARC_GLOB_DAT;
+
+ // If this symbol is forced local, this relocation will
+ // not work properly. That's because ld.so on sparc
+ // (and 32-bit powerpc) expects st_value in the r_addend
+ // of relocations for STB_LOCAL symbols. Curiously the
+ // BFD linker does not promote global hidden symbols to be
+ // STB_LOCAL in the dynamic symbol table like Gold does.
+ gold_assert(!gsym->is_forced_local());
+ got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, rela_dyn,
+ r_type);
+ }
+ else if (!gsym->has_got_offset(GOT_TYPE_STANDARD))
+ {
unsigned int off = got->add_constant(0);
gsym->set_got_offset(GOT_TYPE_STANDARD, off);
+ if (is_ifunc)
+ {
+ // Tell the dynamic linker to use the PLT address
+ // when resolving relocations.
+ if (gsym->is_from_dynobj()
+ && !parameters->options().shared())
+ gsym->set_needs_dynsym_value();
+ }
rela_dyn->add_global_relative(gsym, elfcpp::R_SPARC_RELATIVE,
- got, off, 0);
+ got, off, 0, is_ifunc);
}
- }
+ }
}
break;
@@ -2376,7 +2885,7 @@ Target_sparc<size, big_endian>::Scan::global(
{
const bool is_final = gsym->final_value_is_known();
const tls::Tls_optimization optimized_type
- = optimize_tls_reloc(is_final, r_type);
+ = optimize_tls_reloc(is_final, r_type);
switch (r_type)
{
case elfcpp::R_SPARC_TLS_GD_HI22: // Global-dynamic
@@ -2385,18 +2894,18 @@ Target_sparc<size, big_endian>::Scan::global(
case elfcpp::R_SPARC_TLS_GD_CALL:
if (optimized_type == tls::TLSOPT_NONE)
{
- // Create a pair of GOT entries for the module index and
- // dtv-relative offset.
- Output_data_got<size, big_endian>* got
- = target->got_section(symtab, layout);
- got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_PAIR,
- target->rela_dyn_section(layout),
- (size == 64 ?
- elfcpp::R_SPARC_TLS_DTPMOD64 :
- elfcpp::R_SPARC_TLS_DTPMOD32),
- (size == 64 ?
- elfcpp::R_SPARC_TLS_DTPOFF64 :
- elfcpp::R_SPARC_TLS_DTPOFF32));
+ // Create a pair of GOT entries for the module index and
+ // dtv-relative offset.
+ Output_data_got<size, big_endian>* got
+ = target->got_section(symtab, layout);
+ got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
+ target->rela_dyn_section(layout),
+ (size == 64
+ ? elfcpp::R_SPARC_TLS_DTPMOD64
+ : elfcpp::R_SPARC_TLS_DTPMOD32),
+ (size == 64
+ ? elfcpp::R_SPARC_TLS_DTPOFF64
+ : elfcpp::R_SPARC_TLS_DTPOFF32));
// Emit R_SPARC_WPLT30 against "__tls_get_addr"
if (r_type == elfcpp::R_SPARC_TLS_GD_CALL)
@@ -2404,14 +2913,14 @@ Target_sparc<size, big_endian>::Scan::global(
}
else if (optimized_type == tls::TLSOPT_TO_IE)
{
- // Create a GOT entry for the tp-relative offset.
- Output_data_got<size, big_endian>* got
- = target->got_section(symtab, layout);
- got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET,
- target->rela_dyn_section(layout),
- (size == 64 ?
- elfcpp::R_SPARC_TLS_TPOFF64 :
- elfcpp::R_SPARC_TLS_TPOFF32));
+ // Create a GOT entry for the tp-relative offset.
+ Output_data_got<size, big_endian>* got
+ = target->got_section(symtab, layout);
+ got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
+ target->rela_dyn_section(layout),
+ (size == 64 ?
+ elfcpp::R_SPARC_TLS_TPOFF64 :
+ elfcpp::R_SPARC_TLS_TPOFF32));
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_global(object, r_type, gsym);
@@ -2462,11 +2971,11 @@ Target_sparc<size, big_endian>::Scan::global(
// Create a GOT entry for the tp-relative offset.
Output_data_got<size, big_endian>* got
= target->got_section(symtab, layout);
- got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET,
- target->rela_dyn_section(layout),
- (size == 64 ?
- elfcpp::R_SPARC_TLS_TPOFF64 :
- elfcpp::R_SPARC_TLS_TPOFF32));
+ got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
+ target->rela_dyn_section(layout),
+ (size == 64
+ ? elfcpp::R_SPARC_TLS_TPOFF64
+ : elfcpp::R_SPARC_TLS_TPOFF32));
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_global(object, r_type, gsym);
@@ -2480,7 +2989,9 @@ Target_sparc<size, big_endian>::Scan::global(
case elfcpp::R_SPARC_COPY:
case elfcpp::R_SPARC_GLOB_DAT:
case elfcpp::R_SPARC_JMP_SLOT:
+ case elfcpp::R_SPARC_JMP_IREL:
case elfcpp::R_SPARC_RELATIVE:
+ case elfcpp::R_SPARC_IRELATIVE:
case elfcpp::R_SPARC_TLS_DTPMOD64:
case elfcpp::R_SPARC_TLS_DTPMOD32:
case elfcpp::R_SPARC_TLS_DTPOFF64:
@@ -2580,8 +3091,11 @@ void
Target_sparc<size, big_endian>::do_finalize_sections(
Layout* layout,
const Input_objects*,
- Symbol_table*)
+ Symbol_table* symtab)
{
+ if (this->plt_)
+ this->plt_->emit_pending_ifunc_relocs();
+
// Fill in some more dynamic tags.
const Reloc_section* rel_plt = (this->plt_ == NULL
? NULL
@@ -2593,6 +3107,47 @@ Target_sparc<size, big_endian>::do_finalize_sections(
// relocs.
if (this->copy_relocs_.any_saved_relocs())
this->copy_relocs_.emit(this->rela_dyn_section(layout));
+
+ if (parameters->doing_static_link()
+ && (this->plt_ == NULL || !this->plt_->has_ifunc_section()))
+ {
+ // If linking statically, make sure that the __rela_iplt symbols
+ // were defined if necessary, even if we didn't create a PLT.
+ static const Define_symbol_in_segment syms[] =
+ {
+ {
+ "__rela_iplt_start", // name
+ elfcpp::PT_LOAD, // segment_type
+ elfcpp::PF_W, // segment_flags_set
+ elfcpp::PF(0), // segment_flags_clear
+ 0, // value
+ 0, // size
+ elfcpp::STT_NOTYPE, // type
+ elfcpp::STB_GLOBAL, // binding
+ elfcpp::STV_HIDDEN, // visibility
+ 0, // nonvis
+ Symbol::SEGMENT_START, // offset_from_base
+ true // only_if_ref
+ },
+ {
+ "__rela_iplt_end", // name
+ elfcpp::PT_LOAD, // segment_type
+ elfcpp::PF_W, // segment_flags_set
+ elfcpp::PF(0), // segment_flags_clear
+ 0, // value
+ 0, // size
+ elfcpp::STT_NOTYPE, // type
+ elfcpp::STB_GLOBAL, // binding
+ elfcpp::STV_HIDDEN, // visibility
+ 0, // nonvis
+ Symbol::SEGMENT_START, // offset_from_base
+ true // only_if_ref
+ }
+ };
+
+ symtab->define_symbols(layout, 2, syms,
+ layout->script_options()->saw_sections_clause());
+ }
}
// Perform a relocation.
@@ -2612,6 +3167,7 @@ Target_sparc<size, big_endian>::Relocate::relocate(
typename elfcpp::Elf_types<size>::Elf_Addr address,
section_size_type view_size)
{
+ bool orig_is_ifunc = psymval->is_ifunc_symbol();
r_type &= 0xff;
if (this->ignore_gd_add_)
@@ -2629,6 +3185,7 @@ Target_sparc<size, big_endian>::Relocate::relocate(
view -= 4;
typedef Sparc_relocate_functions<size, big_endian> Reloc;
+ const Sized_relobj_file<size, big_endian>* object = relinfo->object;
// Pick the value to use for symbols defined in shared objects.
Symbol_value<size> symval;
@@ -2637,39 +3194,61 @@ Target_sparc<size, big_endian>::Relocate::relocate(
{
elfcpp::Elf_Xword value;
- value = target->plt_section()->address() + gsym->plt_offset();
+ value = target->plt_address_for_global(gsym) + gsym->plt_offset();
symval.set_output_value(value);
psymval = &symval;
}
+ else if (gsym == NULL && orig_is_ifunc)
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+ if (object->local_has_plt_offset(r_sym))
+ {
+ symval.set_output_value(target->plt_address_for_local(object, r_sym)
+ + object->local_plt_offset(r_sym));
+ psymval = &symval;
+ }
+ }
- const Sized_relobj_file<size, big_endian>* object = relinfo->object;
const elfcpp::Elf_Xword addend = rela.get_r_addend();
// Get the GOT offset if needed. Unlike i386 and x86_64, our GOT
// pointer points to the beginning, not the end, of the table.
// So we just use the plain offset.
unsigned int got_offset = 0;
+ bool gdop_valid = false;
switch (r_type)
{
case elfcpp::R_SPARC_GOTDATA_OP:
case elfcpp::R_SPARC_GOTDATA_OP_HIX22:
case elfcpp::R_SPARC_GOTDATA_OP_LOX10:
+ // If this is local, we did not create a GOT entry because we
+ // intend to transform this into a GOT relative relocation.
+ if (gsym == NULL
+ || (gsym->is_defined()
+ && !gsym->is_from_dynobj()
+ && !gsym->is_preemptible()
+ && !orig_is_ifunc))
+ {
+ got_offset = psymval->value(object, 0) - target->got_address();
+ gdop_valid = true;
+ break;
+ }
case elfcpp::R_SPARC_GOT10:
case elfcpp::R_SPARC_GOT13:
case elfcpp::R_SPARC_GOT22:
if (gsym != NULL)
- {
- gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
- got_offset = gsym->got_offset(GOT_TYPE_STANDARD);
- }
+ {
+ gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
+ got_offset = gsym->got_offset(GOT_TYPE_STANDARD);
+ }
else
- {
- unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
- got_offset = object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
- }
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+ gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
+ got_offset = object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
+ }
break;
default:
@@ -2693,7 +3272,7 @@ Target_sparc<size, big_endian>::Relocate::relocate(
if (rela.get_r_offset() & 0x1)
{
// The assembler can sometimes emit unaligned relocations
- // for dwarf2 cfi directives.
+ // for dwarf2 cfi directives.
Reloc::ua16(view, object, psymval, addend);
}
else
@@ -2707,7 +3286,7 @@ Target_sparc<size, big_endian>::Relocate::relocate(
if (rela.get_r_offset() & 0x3)
{
// The assembler can sometimes emit unaligned relocations
- // for dwarf2 cfi directives.
+ // for dwarf2 cfi directives.
Reloc::ua32(view, object, psymval, addend);
}
else
@@ -2735,6 +3314,8 @@ Target_sparc<size, big_endian>::Relocate::relocate(
case elfcpp::R_SPARC_WDISP30:
case elfcpp::R_SPARC_WPLT30:
Reloc::wdisp30(view, object, psymval, addend, address);
+ if (target->may_relax())
+ relax_call(target, view, rela, view_size);
break;
case elfcpp::R_SPARC_WDISP22:
@@ -2749,6 +3330,10 @@ Target_sparc<size, big_endian>::Relocate::relocate(
Reloc::wdisp16(view, object, psymval, addend, address);
break;
+ case elfcpp::R_SPARC_WDISP10:
+ Reloc::wdisp10(view, object, psymval, addend, address);
+ break;
+
case elfcpp::R_SPARC_HI22:
Reloc::hi22(view, object, psymval, addend);
break;
@@ -2770,14 +3355,37 @@ Target_sparc<size, big_endian>::Relocate::relocate(
break;
case elfcpp::R_SPARC_GOTDATA_OP:
+ if (gdop_valid)
+ {
+ typedef typename elfcpp::Swap<32, true>::Valtype Insntype;
+ Insntype* wv = reinterpret_cast<Insntype*>(view);
+ Insntype val;
+
+ // {ld,ldx} [%rs1 + %rs2], %rd --> add %rs1, %rs2, %rd
+ val = elfcpp::Swap<32, true>::readval(wv);
+ val = 0x80000000 | (val & 0x3e07c01f);
+ elfcpp::Swap<32, true>::writeval(wv, val);
+ }
break;
case elfcpp::R_SPARC_GOTDATA_OP_LOX10:
+ if (gdop_valid)
+ {
+ Reloc::gdop_lox10(view, got_offset, addend);
+ break;
+ }
+ /* Fall through. */
case elfcpp::R_SPARC_GOT13:
Reloc::rela32_13(view, got_offset, addend);
break;
case elfcpp::R_SPARC_GOTDATA_OP_HIX22:
+ if (gdop_valid)
+ {
+ Reloc::gdop_hix22(view, got_offset, addend);
+ break;
+ }
+ /* Fall through. */
case elfcpp::R_SPARC_GOT22:
Reloc::hi22(view, got_offset, addend);
break;
@@ -2831,7 +3439,7 @@ Target_sparc<size, big_endian>::Relocate::relocate(
if (rela.get_r_offset() & 0x7)
{
// The assembler can sometimes emit unaligned relocations
- // for dwarf2 cfi directives.
+ // for dwarf2 cfi directives.
Reloc::ua64(view, object, psymval, addend);
}
else
@@ -2900,6 +3508,10 @@ Target_sparc<size, big_endian>::Relocate::relocate(
Reloc::lox10(view, object, psymval, addend);
break;
+ case elfcpp::R_SPARC_H34:
+ Reloc::h34(view, object, psymval, addend);
+ break;
+
case elfcpp::R_SPARC_H44:
Reloc::h44(view, object, psymval, addend);
break;
@@ -2947,7 +3559,9 @@ Target_sparc<size, big_endian>::Relocate::relocate(
case elfcpp::R_SPARC_COPY:
case elfcpp::R_SPARC_GLOB_DAT:
case elfcpp::R_SPARC_JMP_SLOT:
+ case elfcpp::R_SPARC_JMP_IREL:
case elfcpp::R_SPARC_RELATIVE:
+ case elfcpp::R_SPARC_IRELATIVE:
// These are outstanding tls relocs, which are unexpected when
// linking.
case elfcpp::R_SPARC_TLS_DTPMOD64:
@@ -3039,22 +3653,22 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
break;
}
else
- {
- unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
- ? GOT_TYPE_TLS_OFFSET
- : GOT_TYPE_TLS_PAIR);
- if (gsym != NULL)
- {
- gold_assert(gsym->has_got_offset(got_type));
- value = gsym->got_offset(got_type);
- }
- else
- {
- unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym, got_type));
- value = object->local_got_offset(r_sym, got_type);
- }
- if (optimized_type == tls::TLSOPT_TO_IE)
+ {
+ unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
+ ? GOT_TYPE_TLS_OFFSET
+ : GOT_TYPE_TLS_PAIR);
+ if (gsym != NULL)
+ {
+ gold_assert(gsym->has_got_offset(got_type));
+ value = gsym->got_offset(got_type);
+ }
+ else
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+ gold_assert(object->local_has_got_offset(r_sym, got_type));
+ value = object->local_got_offset(r_sym, got_type);
+ }
+ if (optimized_type == tls::TLSOPT_TO_IE)
{
Insntype* wv = reinterpret_cast<Insntype*>(view);
Insntype val;
@@ -3119,10 +3733,10 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
elfcpp::Swap<32, true>::writeval(wv, 0x9001c008);
break;
}
- break;
+ break;
}
- else if (optimized_type == tls::TLSOPT_NONE)
- {
+ else if (optimized_type == tls::TLSOPT_NONE)
+ {
switch (r_type)
{
case elfcpp::R_SPARC_TLS_GD_HI22:
@@ -3149,8 +3763,8 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
break;
}
break;
- }
- }
+ }
+ }
gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
_("unsupported reloc %u"),
r_type);
@@ -3179,10 +3793,10 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
break;
}
else if (optimized_type == tls::TLSOPT_NONE)
- {
- // Relocate the field with the offset of the GOT entry for
- // the module index.
- unsigned int got_offset;
+ {
+ // Relocate the field with the offset of the GOT entry for
+ // the module index.
+ unsigned int got_offset;
got_offset = target->got_mod_index_entry(NULL, NULL, NULL);
switch (r_type)
@@ -3210,8 +3824,8 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
}
break;
}
- break;
- }
+ break;
+ }
gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
_("unsupported reloc %u"),
r_type);
@@ -3352,6 +3966,150 @@ Target_sparc<size, big_endian>::Relocate::relocate_tls(
}
}
+// Relax a call instruction.
+
+template<int size, bool big_endian>
+inline void
+Target_sparc<size, big_endian>::Relocate::relax_call(
+ Target_sparc<size, big_endian>* target,
+ unsigned char* view,
+ const elfcpp::Rela<size, big_endian>& rela,
+ section_size_type view_size)
+{
+ typedef typename elfcpp::Swap<32, true>::Valtype Insntype;
+ Insntype *wv = reinterpret_cast<Insntype*>(view);
+ Insntype call_insn, delay_insn, set_insn;
+ uint32_t op3, reg, off;
+
+ // This code tries to relax call instructions that meet
+ // certain criteria.
+ //
+ // The first criteria is that the call must be such that the return
+ // address which the call writes into %o7 is unused. Two sequences
+ // meet this criteria, and are used to implement tail calls.
+ //
+ // Leaf function tail call:
+ //
+ // or %o7, %g0, %ANY_REG
+ // call FUNC
+ // or %ANY_REG, %g0, %o7
+ //
+ // Non-leaf function tail call:
+ //
+ // call FUNC
+ // restore
+ //
+ // The second criteria is that the call destination is close. If
+ // the displacement can fit in a signed 22-bit immediate field of a
+ // pre-V9 branch, we can do it. If we are generating a 64-bit
+ // object or a 32-bit object with ELF machine type EF_SPARC32PLUS,
+ // and the displacement fits in a signed 19-bit immediate field,
+ // then we can use a V9 branch.
+
+ // Make sure the delay instruction can be safely accessed.
+ if (rela.get_r_offset() + 8 > view_size)
+ return;
+
+ call_insn = elfcpp::Swap<32, true>::readval(wv);
+ delay_insn = elfcpp::Swap<32, true>::readval(wv + 1);
+
+ // Make sure it is really a call instruction.
+ if (((call_insn >> 30) & 0x3) != 1)
+ return;
+
+ if (((delay_insn >> 30) & 0x3) != 2)
+ return;
+
+ // Accept only a restore or an integer arithmetic operation whose
+ // sole side effect is to write the %o7 register (and perhaps set
+ // the condition codes, which are considered clobbered across
+ // function calls).
+ //
+ // For example, we don't want to match a tagged addition or
+ // subtraction. We also don't want to match something like a
+ // divide.
+ //
+ // Specifically we accept add{,cc}, and{,cc}, or{,cc},
+ // xor{,cc}, sub{,cc}, andn{,cc}, orn{,cc}, and xnor{,cc}.
+
+ op3 = (delay_insn >> 19) & 0x3f;
+ reg = (delay_insn >> 25) & 0x1f;
+ if (op3 != 0x3d
+ && ((op3 & 0x28) != 0 || reg != 15))
+ return;
+
+ // For non-restore instructions, make sure %o7 isn't
+ // an input.
+ if (op3 != 0x3d)
+ {
+ // First check RS1
+ reg = (delay_insn >> 14) & 0x15;
+ if (reg == 15)
+ return;
+
+ // And if non-immediate, check RS2
+ if (((delay_insn >> 13) & 1) == 0)
+ {
+ reg = (delay_insn & 0x1f);
+ if (reg == 15)
+ return;
+ }
+ }
+
+ // Now check the branch distance. We are called after the
+ // call has been relocated, so we just have to peek at the
+ // offset contained in the instruction.
+ off = call_insn & 0x3fffffff;
+ if ((off & 0x3fe00000) != 0
+ && (off & 0x3fe00000) != 0x3fe00000)
+ return;
+
+ if ((size == 64 || target->elf_machine_ == elfcpp::EM_SPARC32PLUS)
+ && ((off & 0x3c0000) == 0
+ || (off & 0x3c0000) == 0x3c0000))
+ {
+ // ba,pt %xcc, FUNC
+ call_insn = 0x10680000 | (off & 0x07ffff);
+ }
+ else
+ {
+ // ba FUNC
+ call_insn = 0x10800000 | (off & 0x3fffff);
+ }
+ elfcpp::Swap<32, true>::writeval(wv, call_insn);
+
+ // See if we can NOP out the delay slot instruction. We peek
+ // at the instruction before the call to make sure we're dealing
+ // with exactly the:
+ //
+ // or %o7, %g0, %ANY_REG
+ // call
+ // or %ANY_REG, %g0, %o7
+ //
+ // case. Otherwise this might be a tricky piece of hand written
+ // assembler calculating %o7 in some non-trivial way, and therefore
+ // we can't be sure that NOP'ing out the delay slot is safe.
+ if (op3 == 0x02
+ && rela.get_r_offset() >= 4)
+ {
+ if ((delay_insn & ~(0x1f << 14)) != 0x9e100000)
+ return;
+
+ set_insn = elfcpp::Swap<32, true>::readval(wv - 1);
+ if ((set_insn & ~(0x1f << 25)) != 0x8013c000)
+ return;
+
+ reg = (set_insn >> 25) & 0x1f;
+ if (reg == 0 || reg == 15)
+ return;
+ if (reg != ((delay_insn >> 14) & 0x1f))
+ return;
+
+ // All tests pass, nop it out.
+ elfcpp::Swap<32, true>::writeval(wv + 1, sparc_nop);
+ }
+}
+
// Relocate section data.
template<int size, bool big_endian>
@@ -3486,6 +4244,100 @@ Target_sparc<size, big_endian>::do_dynsym_value(const Symbol* gsym) const
return this->plt_section()->address() + gsym->plt_offset();
}
+// do_make_elf_object to override the same function in the base class.
+// We need to use a target-specific sub-class of
+// Sized_relobj_file<size, big_endian> to process SPARC specific bits
+// of the ELF headers. Hence we need to have our own ELF object creation.
+
+template<int size, bool big_endian>
+Object*
+Target_sparc<size, big_endian>::do_make_elf_object(
+ const std::string& name,
+ Input_file* input_file,
+ off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr)
+{
+ elfcpp::Elf_Half machine = ehdr.get_e_machine();
+ elfcpp::Elf_Word flags = ehdr.get_e_flags();
+ elfcpp::Elf_Word omm, mm;
+
+ switch (machine)
+ {
+ case elfcpp::EM_SPARC32PLUS:
+ this->elf_machine_ = elfcpp::EM_SPARC32PLUS;
+ break;
+
+ case elfcpp::EM_SPARC:
+ case elfcpp::EM_SPARCV9:
+ break;
+
+ default:
+ break;
+ }
+
+ if (!this->elf_flags_set_)
+ {
+ this->elf_flags_ = flags;
+ this->elf_flags_set_ = true;
+ }
+ else
+ {
+ // Accumulate cpu feature bits.
+ this->elf_flags_ |= (flags & (elfcpp::EF_SPARC_32PLUS
+ | elfcpp::EF_SPARC_SUN_US1
+ | elfcpp::EF_SPARC_HAL_R1
+ | elfcpp::EF_SPARC_SUN_US3));
+
+ // Bump the memory model setting to the most restrictive
+ // one we encounter.
+ omm = (this->elf_flags_ & elfcpp::EF_SPARCV9_MM);
+ mm = (flags & elfcpp::EF_SPARCV9_MM);
+ if (omm != mm)
+ {
+ if (mm == elfcpp::EF_SPARCV9_TSO)
+ {
+ this->elf_flags_ &= ~elfcpp::EF_SPARCV9_MM;
+ this->elf_flags_ |= elfcpp::EF_SPARCV9_TSO;
+ }
+ else if (mm == elfcpp::EF_SPARCV9_PSO
+ && omm == elfcpp::EF_SPARCV9_RMO)
+ {
+ this->elf_flags_ &= ~elfcpp::EF_SPARCV9_MM;
+ this->elf_flags_ |= elfcpp::EF_SPARCV9_PSO;
+ }
+ }
+ }
+
+ // Validate that the little-endian flag matches how we've
+ // been instantiated.
+ if (!(flags & elfcpp::EF_SPARC_LEDATA) != big_endian)
+ {
+ if (big_endian)
+ gold_error(_("%s: little endian elf flag set on BE object"),
+ name.c_str());
+ else
+ gold_error(_("%s: little endian elf flag clear on LE object"),
+ name.c_str());
+ }
+
+ return Target::do_make_elf_object(name, input_file, offset, ehdr);
+}
+
+// Adjust ELF file header.
+
+template<int size, bool big_endian>
+void
+Target_sparc<size, big_endian>::do_adjust_elf_header(
+ unsigned char* view,
+ int len) const
+{
+ elfcpp::Ehdr_write<size, big_endian> oehdr(view);
+
+ oehdr.put_e_machine(this->elf_machine_);
+ oehdr.put_e_flags(this->elf_flags_);
+
+ Sized_target<size, big_endian>::do_adjust_elf_header(view, len);
+}
+
// The selector for sparc object files.
template<int size, bool big_endian>
@@ -3498,7 +4350,8 @@ public:
(size == 64 ? "elf64_sparc" : "elf32_sparc"))
{ }
- Target* do_recognize(int machine, int, int)
+ virtual Target*
+ do_recognize(Input_file*, off_t, int machine, int, int)
{
switch (size)
{
@@ -3520,7 +4373,8 @@ public:
return this->instantiate_target();
}
- Target* do_instantiate_target()
+ virtual Target*
+ do_instantiate_target()
{ return new Target_sparc<size, big_endian>(); }
};
diff --git a/binutils-2.22/gold/symtab.cc b/binutils-2.22/gold/symtab.cc
index ff1b5ca..fd81e8bd 100644
--- a/binutils-2.22/gold/symtab.cc
+++ b/binutils-2.22/gold/symtab.cc
@@ -363,14 +363,23 @@ Symbol::should_add_dynsym_entry(Symbol_table* symtab) const
return false;
}
+ // If the symbol was forced dynamic in a --dynamic-list file
+ // or an --export-dynamic-symbol option, add it.
+ if (!this->is_from_dynobj()
+ && (parameters->options().in_dynamic_list(this->name())
+ || parameters->options().is_export_dynamic_symbol(this->name())))
+ {
+ if (!this->is_forced_local())
+ return true;
+ gold_warning(_("Cannot export local symbol '%s'"),
+ this->demangled_name().c_str());
+ return false;
+ }
+
// If the symbol was forced local in a version script, do not add it.
if (this->is_forced_local())
return false;
- // If the symbol was forced dynamic in a --dynamic-list file, add it.
- if (parameters->options().in_dynamic_list(this->name()))
- return true;
-
// If dynamic-list-data was specified, add any STT_OBJECT.
if (parameters->options().dynamic_list_data()
&& !this->is_from_dynobj()
@@ -551,8 +560,8 @@ Symbol_table::is_section_folded(Object* obj, unsigned int shndx) const
&& this->icf_->is_section_folded(obj, shndx));
}
-// For symbols that have been listed with -u option, add them to the
-// work list to avoid gc'ing them.
+// For symbols that have been listed with a -u or --export-dynamic-symbol
+// option, add them to the work list to avoid gc'ing them.
void
Symbol_table::gc_mark_undef_symbols(Layout* layout)
@@ -579,6 +588,28 @@ Symbol_table::gc_mark_undef_symbols(Layout* layout)
}
}
+ for (options::String_set::const_iterator p =
+ parameters->options().export_dynamic_symbol_begin();
+ p != parameters->options().export_dynamic_symbol_end();
+ ++p)
+ {
+ const char* name = p->c_str();
+ Symbol* sym = this->lookup(name);
+ gold_assert(sym != NULL);
+ if (sym->source() == Symbol::FROM_OBJECT
+ && !sym->object()->is_dynamic())
+ {
+ Relobj* obj = static_cast<Relobj*>(sym->object());
+ bool is_ordinary;
+ unsigned int shndx = sym->shndx(&is_ordinary);
+ if (is_ordinary)
+ {
+ gold_assert(this->gc_ != NULL);
+ this->gc_->worklist().push(Section_id(obj, shndx));
+ }
+ }
+ }
+
for (Script_options::referenced_const_iterator p =
layout->script_options()->referenced_begin();
p != layout->script_options()->referenced_end();
@@ -602,20 +633,16 @@ Symbol_table::gc_mark_undef_symbols(Layout* layout)
}
void
-Symbol_table::gc_mark_symbol_for_shlib(Symbol* sym)
+Symbol_table::gc_mark_symbol(Symbol* sym)
{
- if (!sym->is_from_dynobj()
- && sym->is_externally_visible())
+ // Add the object and section to the work list.
+ Relobj* obj = static_cast<Relobj*>(sym->object());
+ bool is_ordinary;
+ unsigned int shndx = sym->shndx(&is_ordinary);
+ if (is_ordinary && shndx != elfcpp::SHN_UNDEF)
{
- //Add the object and section to the work list.
- Relobj* obj = static_cast<Relobj*>(sym->object());
- bool is_ordinary;
- unsigned int shndx = sym->shndx(&is_ordinary);
- if (is_ordinary && shndx != elfcpp::SHN_UNDEF)
- {
- gold_assert(this->gc_!= NULL);
- this->gc_->worklist().push(Section_id(obj, shndx));
- }
+ gold_assert(this->gc_!= NULL);
+ this->gc_->worklist().push(Section_id(obj, shndx));
}
}
@@ -626,16 +653,7 @@ Symbol_table::gc_mark_dyn_syms(Symbol* sym)
{
if (sym->in_dyn() && sym->source() == Symbol::FROM_OBJECT
&& !sym->object()->is_dynamic())
- {
- Relobj* obj = static_cast<Relobj*>(sym->object());
- bool is_ordinary;
- unsigned int shndx = sym->shndx(&is_ordinary);
- if (is_ordinary && shndx != elfcpp::SHN_UNDEF)
- {
- gold_assert(this->gc_ != NULL);
- this->gc_->worklist().push(Section_id(obj, shndx));
- }
- }
+ this->gc_mark_symbol(sym);
}
// Make TO a symbol which forwards to FROM.
@@ -1143,6 +1161,14 @@ Symbol_table::add_from_relobj(
bool is_default_version = false;
bool is_forced_local = false;
+ // FIXME: For incremental links, we don't store version information,
+ // so we need to ignore version symbols for now.
+ if (parameters->incremental_update() && ver != NULL)
+ {
+ namelen = ver - name;
+ ver = NULL;
+ }
+
if (ver != NULL)
{
// The symbol name is of the form foo@VERSION or foo@@VERSION
@@ -1243,11 +1269,16 @@ Symbol_table::add_from_relobj(
if (is_forced_local)
this->force_local(res);
- // If building a shared library using garbage collection, do not
- // treat externally visible symbols as garbage.
- if (parameters->options().gc_sections()
- && parameters->options().shared())
- this->gc_mark_symbol_for_shlib(res);
+ // Do not treat this symbol as garbage if this symbol will be
+ // exported to the dynamic symbol table. This is true when
+ // building a shared library or using --export-dynamic and
+ // the symbol is externally visible.
+ if (parameters->options().gc_sections()
+ && res->is_externally_visible()
+ && !res->is_from_dynobj()
+ && (parameters->options().shared()
+ || parameters->options().export_dynamic()))
+ this->gc_mark_symbol(res);
if (is_defined_in_discarded_section)
res->set_is_defined_in_discarded_section();
@@ -1346,6 +1377,11 @@ Symbol_table::add_from_dynobj(
return;
}
+ // FIXME: For incremental links, we don't store version information,
+ // so we need to ignore version symbols for now.
+ if (parameters->incremental_update())
+ versym = NULL;
+
if (versym != NULL && versym_size / 2 < count)
{
dynobj->error(_("too few symbol versions"));
@@ -1646,6 +1682,7 @@ Symbol_table::define_special_symbol(const char** pname, const char** pversion,
bool* resolve_oldsym)
{
*resolve_oldsym = false;
+ *poldsym = NULL;
// If the caller didn't give us a version, see if we get one from
// the version script.
@@ -2286,6 +2323,12 @@ Symbol_table::do_add_undefined_symbols_from_command_line(Layout* layout)
++p)
this->add_undefined_symbol_from_command_line<size>(p->c_str());
+ for (options::String_set::const_iterator p =
+ parameters->options().export_dynamic_symbol_begin();
+ p != parameters->options().export_dynamic_symbol_end();
+ ++p)
+ this->add_undefined_symbol_from_command_line<size>(p->c_str());
+
for (Script_options::referenced_const_iterator p =
layout->script_options()->referenced_begin();
p != layout->script_options()->referenced_end();
@@ -2809,6 +2852,12 @@ Symbol_table::sized_write_globals(const Stringpool* sympool,
typename elfcpp::Elf_types<size>::Elf_Addr sym_value = sym->value();
typename elfcpp::Elf_types<size>::Elf_Addr dynsym_value = sym_value;
elfcpp::STB binding = sym->binding();
+
+ // If --no-gnu-unique is set, change STB_GNU_UNIQUE to STB_GLOBAL.
+ if (binding == elfcpp::STB_GNU_UNIQUE
+ && !parameters->options().gnu_unique())
+ binding = elfcpp::STB_GLOBAL;
+
switch (sym->source())
{
case Symbol::FROM_OBJECT:
diff --git a/binutils-2.22/gold/symtab.h b/binutils-2.22/gold/symtab.h
index b9b9e00..feed245 100644
--- a/binutils-2.22/gold/symtab.h
+++ b/binutils-2.22/gold/symtab.h
@@ -993,7 +993,12 @@ class Symbol
// index, not one of the special codes from SHN_LORESERVE to
// SHN_HIRESERVE (bit 29).
bool is_ordinary_shndx_ : 1;
- // True if we've seen this symbol in a real ELF object (bit 30).
+ // True if we've seen this symbol in a "real" ELF object (bit 30).
+ // If the symbol has been seen in a relocatable, non-IR, object file,
+ // it's known to be referenced from outside the IR. A reference from
+ // a dynamic object doesn't count as a "real" ELF, and we'll simply
+ // mark the symbol as "visible" from outside the IR. The compiler
+ // can use this distinction to guide its handling of COMDAT symbols.
bool in_real_elf_ : 1;
// True if this symbol is defined in a section which was discarded
// (bit 31).
@@ -1308,10 +1313,9 @@ class Symbol_table
void
gc_mark_undef_symbols(Layout*);
- // During garbage collection, this ensures externally visible symbols
- // are not treated as garbage while building shared objects.
+ // This tells garbage collection that this symbol is referenced.
void
- gc_mark_symbol_for_shlib(Symbol* sym);
+ gc_mark_symbol(Symbol* sym);
// During garbage collection, this keeps sections that correspond to
// symbols seen in dynamic objects.
diff --git a/binutils-2.22/gold/target-reloc.h b/binutils-2.22/gold/target-reloc.h
index 464a3fa..6efcdf4 100644
--- a/binutils-2.22/gold/target-reloc.h
+++ b/binutils-2.22/gold/target-reloc.h
@@ -423,17 +423,17 @@ apply_relocation(const Relocate_info<size, big_endian>* relinfo,
section_size_type view_size)
{
// Construct the ELF relocation in a temporary buffer.
- const int reloc_size = elfcpp::Elf_sizes<64>::rela_size;
+ const int reloc_size = elfcpp::Elf_sizes<size>::rela_size;
unsigned char relbuf[reloc_size];
- elfcpp::Rela<64, false> rel(relbuf);
- elfcpp::Rela_write<64, false> orel(relbuf);
+ elfcpp::Rela<size, big_endian> rel(relbuf);
+ elfcpp::Rela_write<size, big_endian> orel(relbuf);
orel.put_r_offset(r_offset);
- orel.put_r_info(elfcpp::elf_r_info<64>(0, r_type));
+ orel.put_r_info(elfcpp::elf_r_info<size>(0, r_type));
orel.put_r_addend(r_addend);
// Setup a Symbol_value for the global symbol.
- const Sized_symbol<64>* sym = static_cast<const Sized_symbol<64>*>(gsym);
- Symbol_value<64> symval;
+ const Sized_symbol<size>* sym = static_cast<const Sized_symbol<size>*>(gsym);
+ Symbol_value<size> symval;
gold_assert(sym->has_symtab_index() && sym->symtab_index() != -1U);
symval.set_output_symtab_index(sym->symtab_index());
symval.set_output_value(sym->value());
diff --git a/binutils-2.22/gold/target-select.cc b/binutils-2.22/gold/target-select.cc
index 9370a87..e17cb7d 100644
--- a/binutils-2.22/gold/target-select.cc
+++ b/binutils-2.22/gold/target-select.cc
@@ -1,6 +1,7 @@
// target-select.cc -- select a target for an object file
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -98,8 +99,9 @@ Target_selector::do_target_bfd_name(const Target* target)
// Find the target for an ELF file.
Target*
-select_target(int machine, int size, bool is_big_endian, int osabi,
- int abiversion)
+select_target(Input_file* input_file, off_t offset,
+ int machine, int size, bool is_big_endian,
+ int osabi, int abiversion)
{
for (Target_selector* p = target_selectors; p != NULL; p = p->next())
{
@@ -108,7 +110,8 @@ select_target(int machine, int size, bool is_big_endian, int osabi,
&& p->get_size() == size
&& (p->is_big_endian() ? is_big_endian : !is_big_endian))
{
- Target* ret = p->recognize(machine, osabi, abiversion);
+ Target* ret = p->recognize(input_file, offset,
+ machine, osabi, abiversion);
if (ret != NULL)
return ret;
}
diff --git a/binutils-2.22/gold/target-select.h b/binutils-2.22/gold/target-select.h
index 310c0b9..2e16c2a 100644
--- a/binutils-2.22/gold/target-select.h
+++ b/binutils-2.22/gold/target-select.h
@@ -1,6 +1,7 @@
// target-select.h -- select a target for an object file -*- C++ -*-
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -30,6 +31,7 @@
namespace gold
{
+class Input_file;
class Target;
class Target_selector;
@@ -76,8 +78,9 @@ class Target_selector
// If we can handle this target, return a pointer to a target
// structure. The size and endianness are known.
Target*
- recognize(int machine, int osabi, int abiversion)
- { return this->do_recognize(machine, osabi, abiversion); }
+ recognize(Input_file* input_file, off_t offset,
+ int machine, int osabi, int abiversion)
+ { return this->do_recognize(input_file, offset, machine, osabi, abiversion); }
// If NAME matches the target, return a pointer to a target
// structure.
@@ -160,7 +163,7 @@ class Target_selector
// checks, or to check for multiple machine codes if the machine_
// field is EM_NONE.
virtual Target*
- do_recognize(int, int, int)
+ do_recognize(Input_file*, off_t, int, int, int)
{ return this->instantiate_target(); }
// Recognize a target by name. When this is called we already know
@@ -241,7 +244,8 @@ class Target_selector
// Select the target for an ELF file.
extern Target*
-select_target(int machine, int size, bool big_endian, int osabi,
+select_target(Input_file*, off_t,
+ int machine, int size, bool big_endian, int osabi,
int abiversion);
// Select a target using a BFD name.
diff --git a/binutils-2.22/gold/target.cc b/binutils-2.22/gold/target.cc
index 091f9d3..a47d74f 100644
--- a/binutils-2.22/gold/target.cc
+++ b/binutils-2.22/gold/target.cc
@@ -217,13 +217,13 @@ Sized_target<size, big_endian>::do_adjust_elf_header(unsigned char* view,
{
gold_assert(len == elfcpp::Elf_sizes<size>::ehdr_size);
- elfcpp::Ehdr<size, false> ehdr(view);
+ elfcpp::Ehdr<size, big_endian> ehdr(view);
unsigned char e_ident[elfcpp::EI_NIDENT];
memcpy(e_ident, ehdr.get_e_ident(), elfcpp::EI_NIDENT);
e_ident[elfcpp::EI_OSABI] = osabi;
- elfcpp::Ehdr_write<size, false> oehdr(view);
+ elfcpp::Ehdr_write<size, big_endian> oehdr(view);
oehdr.put_e_ident(e_ident);
}
}
diff --git a/binutils-2.22/gold/target.h b/binutils-2.22/gold/target.h
index a4aab43..81c8114 100644
--- a/binutils-2.22/gold/target.h
+++ b/binutils-2.22/gold/target.h
@@ -1,6 +1,7 @@
// target.h -- target support for gold -*- C++ -*-
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -49,15 +50,14 @@ template<int size, bool big_endian>
class Sized_relobj_file;
class Relocatable_relocs;
template<int size, bool big_endian>
-class Relocate_info;
+struct Relocate_info;
class Reloc_symbol_changes;
class Symbol;
template<int size>
class Sized_symbol;
class Symbol_table;
class Output_data;
-template<int size, bool big_endian>
-class Output_data_got;
+class Output_data_got_base;
class Output_section;
class Input_objects;
class Task;
@@ -143,6 +143,16 @@ class Target
this->abi_pagesize());
}
+ // Return whether PF_X segments must contain nothing but the contents of
+ // SHF_EXECINSTR sections (no non-executable data, no headers).
+ bool
+ isolate_execinstr() const
+ { return this->pti_->isolate_execinstr; }
+
+ uint64_t
+ rosegment_gap() const
+ { return this->pti_->rosegment_gap; }
+
// If we see some object files with .note.GNU-stack sections, and
// some objects files without them, this returns whether we should
// consider the object files without them to imply that the stack
@@ -345,7 +355,7 @@ class Target
return pass < 2;
return this->do_relax(pass, input_objects, symtab, layout, task);
- }
+ }
// Return the target-specific name of attributes section. This is
// NULL if a target does not use attributes section or if it uses
@@ -365,7 +375,7 @@ class Target
{
return ((this->pti_->attributes_section != NULL
&& strcmp(name, this->pti_->attributes_section) == 0)
- || strcmp(name, ".gnu.attributes") == 0);
+ || strcmp(name, ".gnu.attributes") == 0);
}
// Return a bit mask of argument types for attribute with TAG.
@@ -384,7 +394,7 @@ class Target
// which may be used for expensive, target-specific initialization.
void
select_as_default_target()
- { this->do_select_as_default_target(); }
+ { this->do_select_as_default_target(); }
// Return the value to store in the EI_OSABI field in the ELF
// header.
@@ -436,6 +446,11 @@ class Target
uint64_t abi_pagesize;
// The common page size used by actual implementations.
uint64_t common_pagesize;
+ // Whether PF_X segments must contain nothing but the contents of
+ // SHF_EXECINSTR sections (no non-executable data, no headers).
+ bool isolate_execinstr;
+ // If nonzero, distance from the text segment to the read-only segment.
+ uint64_t rosegment_gap;
// The special section index for small common symbols; SHN_UNDEF
// if none.
elfcpp::Elf_Half small_common_shndx;
@@ -563,7 +578,7 @@ class Target
this->processor_specific_flags_ = flags;
this->are_processor_specific_flags_set_ = true;
}
-
+
#ifdef HAVE_TARGET_32_LITTLE
// Virtual functions which may be overridden by the child class.
virtual Object*
@@ -620,7 +635,7 @@ class Target
section_offset_type offset, size_t len) const;
// This must be overridden by the child class if it has target-specific
- // attributes subsection in the attribute section.
+ // attributes subsection in the attribute section.
virtual int
do_attribute_arg_type(int) const
{ gold_unreachable(); }
@@ -789,7 +804,7 @@ class Sized_target : public Target
section_size_type view_size,
unsigned char* reloc_view,
section_size_type reloc_view_size) = 0;
-
+
// Perform target-specific processing in a relocatable link. This is
// only used if we use the relocation strategy RELOC_SPECIAL.
// RELINFO points to a Relocation_info structure. SH_TYPE is the relocation
@@ -819,7 +834,7 @@ class Sized_target : public Target
section_size_type /* view_size */,
unsigned char* /* preloc_out*/)
{ gold_unreachable(); }
-
+
// Return the number of entries in the GOT. This is only used for
// laying out the incremental link info sections. A target needs
// to implement this to support incremental linking.
@@ -855,7 +870,7 @@ class Sized_target : public Target
// Create the GOT and PLT sections for an incremental update.
// A target needs to implement this to support incremental linking.
- virtual Output_data_got<size, big_endian>*
+ virtual Output_data_got_base*
init_got_plt_for_update(Symbol_table*,
Layout*,
unsigned int /* got_count */,
diff --git a/binutils-2.22/gold/testsuite/Makefile.am b/binutils-2.22/gold/testsuite/Makefile.am
index fdb37e5..b8b88e8 100644
--- a/binutils-2.22/gold/testsuite/Makefile.am
+++ b/binutils-2.22/gold/testsuite/Makefile.am
@@ -94,6 +94,9 @@ object_unittest_SOURCES = object_unittest.cc
check_PROGRAMS += binary_unittest
binary_unittest_SOURCES = binary_unittest.cc
+check_PROGRAMS += leb128_unittest
+leb128_unittest_SOURCES = leb128_unittest.cc
+
endif NATIVE_OR_CROSS_LINKER
# ---------------------------------------------------------------------
@@ -861,7 +864,7 @@ initpri1_LDADD =
check_PROGRAMS += initpri2
initpri2_SOURCES = initpri2.c
initpri2_DEPENDENCIES = gcctestdir/ld
-initpri2_LDFLAGS = -Bgcctestdir/
+initpri2_LDFLAGS = -Bgcctestdir/ -Wl,--ctors-in-init-array
initpri2_LDADD =
check_PROGRAMS += initpri3a
@@ -870,11 +873,16 @@ initpri3a_DEPENDENCIES = gcctestdir/ld
initpri3a_LDFLAGS = -Bgcctestdir/
initpri3a_LDADD =
-check_PROGRAMS += initpri3b
-initpri3b_SOURCES = initpri3.c
-initpri3b_DEPENDENCIES = gcctestdir/ld
-initpri3b_LDFLAGS = -Bgcctestdir/ -Wl,--no-ctors-in-init-array
-initpri3b_LDADD =
+# This test fails on targets not using .ctors and .dtors sections (e.g. ARM
+# EABI). Given that gcc is moving towards using .init_array in all cases,
+# this test is commented out. A better fix would be checking whether gcc
+# uses .ctors or .init_array sections in configure.
+
+# check_PROGRAMS += initpri3b
+# initpri3b_SOURCES = initpri3.c
+# initpri3b_DEPENDENCIES = gcctestdir/ld
+# initpri3b_LDFLAGS = -Bgcctestdir/ -Wl,--no-ctors-in-init-array
+# initpri3b_LDADD =
# Test --detect-odr-violations
check_SCRIPTS += debug_msg.sh
@@ -1510,6 +1518,20 @@ unused.o: unused.c
unused.c:
@cp /dev/null $@
+check_SCRIPTS += plugin_final_layout.sh
+check_DATA += plugin_final_layout.stdout
+plugin_final_layout.o: plugin_final_layout.cc
+ $(CXXCOMPILE) -O0 -c -ffunction-sections -fdata-sections -g -o $@ $<
+plugin_final_layout: plugin_final_layout.o plugin_section_order.so gcctestdir/ld
+ $(CXXLINK) -Bgcctestdir/ -Wl,--plugin,"./plugin_section_order.so" plugin_final_layout.o
+plugin_final_layout.stdout: plugin_final_layout
+ $(TEST_NM) -n plugin_final_layout > plugin_final_layout.stdout
+
+plugin_section_order.so: plugin_section_order.o
+ $(LINK) -Bgcctestdir/ -shared plugin_section_order.o
+plugin_section_order.o: plugin_section_order.c
+ $(COMPILE) -O0 -c -fpic -o $@ $<
+
endif PLUGINS
check_PROGRAMS += exclude_libs_test
@@ -1651,7 +1673,7 @@ no_version_test.stdout: libno_version_test.so
if IFUNC
ifuncmod1.o: ifuncmod1.c
- $(COMPILE) -c -fpic -o $@ $<
+ $(COMPILE) -c -fPIC -o $@ $<
ifuncmod1.so: ifuncmod1.o gcctestdir/ld
$(LINK) -Bgcctestdir/ -shared ifuncmod1.o
@@ -1659,9 +1681,9 @@ ifuncdep1.o: ifuncmod1.c
$(COMPILE) -c -o $@ $<
ifuncmain1pic.o: ifuncmain1.c
- $(COMPILE) -c -fpic -o $@ $<
+ $(COMPILE) -c -fPIC -o $@ $<
ifuncmain1pie.o: ifuncmain1.c
- $(COMPILE) -c -fpie -o $@ $<
+ $(COMPILE) -c -fPIE -o $@ $<
if HAVE_STATIC
if IFUNC_STATIC
@@ -1695,7 +1717,7 @@ ifuncmain1vis_LDADD = ifuncmod1.so
check_PROGRAMS += ifuncmain1vispic
ifuncmain1vispic.o: ifuncmain1vis.c
- $(COMPILE) -c -fpic -o $@ $<
+ $(COMPILE) -c -fPIC -o $@ $<
ifuncmain1vispic: ifuncmain1vispic.o ifuncmod1.so gcctestdir/ld
$(LINK) -Bgcctestdir/ ifuncmain1pic.o ifuncmod1.so -Wl,-R,.
@@ -1709,7 +1731,7 @@ ifuncmain1pie: ifuncmain1pie.o ifuncmod1.so gcctestdir/ld
check_PROGRAMS += ifuncmain1vispie
ifuncmain1vispie.o: ifuncmain1vis.c
- $(COMPILE) -c -fpie -o $@ $<
+ $(COMPILE) -c -fPIE -o $@ $<
ifuncmain1vispie: ifuncmain1vispie.o ifuncmod1.so gcctestdir/ld
$(LINK) -Bgcctestdir/ -pie ifuncmain1vispie.o ifuncmod1.so -Wl,-R,.
@@ -1718,10 +1740,10 @@ ifuncmain1staticpie: ifuncmain1pie.o ifuncmod1.o gcctestdir/ld
$(LINK) -Bgcctestdir/ -pie ifuncmain1pie.o ifuncmod1.o
ifuncmain2pic.o: ifuncmain2.c
- $(COMPILE) -c -fpic -o $@ $<
+ $(COMPILE) -c -fPIC -o $@ $<
ifuncdep2pic.o: ifuncdep2.c
- $(COMPILE) -c -fpic -o $@ $<
+ $(COMPILE) -c -fPIC -o $@ $<
if HAVE_STATIC
if IFUNC_STATIC
@@ -1748,7 +1770,7 @@ ifuncmain2pic: ifuncmain2pic.o ifuncdep2pic.o gcctestdir/ld
$(LINK) -Bgcctestdir/ ifuncmain2pic.o ifuncdep2pic.o
ifuncmod3.o: ifuncmod3.c
- $(COMPILE) -c -fpic -o $@ $<
+ $(COMPILE) -c -fPIC -o $@ $<
ifuncmod3.so: ifuncmod3.o gcctestdir/ld
$(LINK) -Bgcctestdir/ -shared ifuncmod3.o
@@ -1759,7 +1781,7 @@ ifuncmain3_LDFLAGS = -Bgcctestdir/ -Wl,--export-dynamic -Wl,-R,.
ifuncmain3_LDADD = -ldl
ifuncmain4pic.o: ifuncmain4.c
- $(COMPILE) -c -fpic -o $@ $<
+ $(COMPILE) -c -fPIC -o $@ $<
if HAVE_STATIC
if IFUNC_STATIC
@@ -1782,13 +1804,13 @@ ifuncmain4_LDFLAGS = -Bgcctestdir/
ifuncmain4_LDADD =
ifuncmain5pic.o: ifuncmain5.c
- $(COMPILE) -c -fpic -o $@ $<
+ $(COMPILE) -c -fPIC -o $@ $<
ifuncmain5pie.o: ifuncmain5.c
- $(COMPILE) -c -fpie -o $@ $<
+ $(COMPILE) -c -fPIE -o $@ $<
ifuncmod5.o: ifuncmod5.c
- $(COMPILE) -c -fpic -o $@ $<
+ $(COMPILE) -c -fPIC -o $@ $<
ifuncmod5.so: ifuncmod5.o gcctestdir/ld
$(LINK) -Bgcctestdir/ -shared ifuncmod5.o
@@ -1828,10 +1850,10 @@ ifuncmain5pie: ifuncmain5pie.o ifuncmod5.so gcctestdir/ld
$(LINK) -Bgcctestdir/ -pie ifuncmain5pie.o ifuncmod5.so -Wl,-R,.
ifuncmain6pie.o: ifuncmain6pie.c
- $(COMPILE) -c -fpie -o $@ $<
+ $(COMPILE) -c -fPIE -o $@ $<
ifuncmod6.o: ifuncmod6.c
- $(COMPILE) -c -fpic -o $@ $<
+ $(COMPILE) -c -fPIC -o $@ $<
ifuncmod6.so: ifuncmod6.o gcctestdir/ld
$(LINK) -Bgcctestdir/ -shared ifuncmod6.o
@@ -1840,10 +1862,10 @@ ifuncmain6pie: ifuncmain6pie.o ifuncmod6.so gcctestdir/ld
$(LINK) -Bgcctestdir/ -pie ifuncmain6pie.o ifuncmod6.so -Wl,-R,.
ifuncmain7pic.o: ifuncmain7.c
- $(COMPILE) -c -fpic -o $@ $<
+ $(COMPILE) -c -fPIC -o $@ $<
ifuncmain7pie.o: ifuncmain7.c
- $(COMPILE) -c -fpie -o $@ $<
+ $(COMPILE) -c -fPIE -o $@ $<
if HAVE_STATIC
if IFUNC_STATIC
@@ -1875,9 +1897,9 @@ ifuncmain7pie: ifuncmain7pie.o gcctestdir/ld
check_PROGRAMS += ifuncvar
ifuncvar1_pic.o: ifuncvar1.c
- $(COMPILE) -c -fpic -o $@ $<
+ $(COMPILE) -c -fPIC -o $@ $<
ifuncvar2_pic.o: ifuncvar2.c
- $(COMPILE) -c -fpic -o $@ $<
+ $(COMPILE) -c -fPIC -o $@ $<
ifuncvar.so: ifuncvar1_pic.o ifuncvar2_pic.o gcctestdir/ld
$(LINK) -Bgcctestdir/ -shared ifuncvar1_pic.o ifuncvar2_pic.o
ifuncvar_SOURCES = ifuncvar3.c
@@ -1945,6 +1967,58 @@ memory_test: memory_test.o gcctestdir/ld $(srcdir)/memory_test.t
memory_test.stdout: memory_test
$(TEST_READELF) -lWS $< > $@
+if HAVE_PUBNAMES
+
+# Test that --gdb-index functions correctly without gcc-generated pubnames.
+check_SCRIPTS += gdb_index_test_1.sh
+check_DATA += gdb_index_test_1.stdout
+MOSTLYCLEANFILES += gdb_index_test_1.stdout gdb_index_test_1
+gdb_index_test.o: gdb_index_test.cc
+ $(CXXCOMPILE) -O0 -g -gno-pubnames -c -o $@ $<
+gdb_index_test_1: gdb_index_test.o gcctestdir/ld
+ $(CXXLINK) -Bgcctestdir/ -Wl,--gdb-index $<
+gdb_index_test_1.stdout: gdb_index_test_1
+ $(TEST_READELF) --debug-dump=gdb_index $< > $@
+
+if HAVE_ZLIB
+
+# Test that --gdb-index functions correctly with compressed debug sections.
+check_SCRIPTS += gdb_index_test_2.sh
+check_DATA += gdb_index_test_2.stdout
+MOSTLYCLEANFILES += gdb_index_test_2.stdout gdb_index_test_2
+gdb_index_test_cdebug.o: gdb_index_test.cc
+ $(CXXCOMPILE) -Bgcctestdir/ -O0 -g -Wa,--compress-debug-sections -c -o $@ $<
+gdb_index_test_2: gdb_index_test_cdebug.o gcctestdir/ld
+ $(CXXLINK) -Bgcctestdir/ -Wl,--gdb-index $<
+gdb_index_test_2.stdout: gdb_index_test_2
+ $(TEST_READELF) --debug-dump=gdb_index $< > $@
+
+endif HAVE_ZLIB
+
+# Another simple C test (DW_AT_high_pc encoding) for --gdb-index.
+check_SCRIPTS += gdb_index_test_3.sh
+check_DATA += gdb_index_test_3.stdout
+MOSTLYCLEANFILES += gdb_index_test_3.stdout gdb_index_test_3
+gdb_index_test_3.o: gdb_index_test_3.c
+ $(COMPILE) -O0 -g -c -o $@ $<
+gdb_index_test_3: gdb_index_test_3.o gcctestdir/ld
+ $(LINK) -Bgcctestdir/ -Wl,--gdb-index,--fatal-warnings $<
+gdb_index_test_3.stdout: gdb_index_test_3
+ $(TEST_READELF) --debug-dump=gdb_index $< > $@
+
+# Test that --gdb-index functions correctly with gcc-generated pubnames.
+check_SCRIPTS += gdb_index_test_4.sh
+check_DATA += gdb_index_test_4.stdout
+MOSTLYCLEANFILES += gdb_index_test_4.stdout gdb_index_test_4
+gdb_index_test_pub.o: gdb_index_test.cc
+ $(CXXCOMPILE) -O0 -g -gpubnames -c -o $@ $<
+gdb_index_test_4: gdb_index_test_pub.o gcctestdir/ld
+ $(CXXLINK) -Bgcctestdir/ -Wl,--gdb-index $<
+gdb_index_test_4.stdout: gdb_index_test_4
+ $(TEST_READELF) --debug-dump=gdb_index $< > $@
+
+endif HAVE_PUBNAMES
+
# End-to-end incremental linking tests.
# Incremental linking is currently supported only on the x86_64 target.
diff --git a/binutils-2.22/gold/testsuite/Makefile.in b/binutils-2.22/gold/testsuite/Makefile.in
index 67149fb..4887827 100644
--- a/binutils-2.22/gold/testsuite/Makefile.in
+++ b/binutils-2.22/gold/testsuite/Makefile.in
@@ -54,7 +54,18 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
$(am__EXEEXT_34) $(am__EXEEXT_35) $(am__EXEEXT_36) \
$(am__EXEEXT_37) $(am__EXEEXT_38)
@NATIVE_OR_CROSS_LINKER_TRUE@am__append_1 = object_unittest \
-@NATIVE_OR_CROSS_LINKER_TRUE@ binary_unittest
+@NATIVE_OR_CROSS_LINKER_TRUE@ binary_unittest leb128_unittest
+
+# This test fails on targets not using .ctors and .dtors sections (e.g. ARM
+# EABI). Given that gcc is moving towards using .init_array in all cases,
+# this test is commented out. A better fix would be checking whether gcc
+# uses .ctors or .init_array sections in configure.
+
+# check_PROGRAMS += initpri3b
+# initpri3b_SOURCES = initpri3.c
+# initpri3b_DEPENDENCIES = gcctestdir/ld
+# initpri3b_LDFLAGS = -Bgcctestdir/ -Wl,--no-ctors-in-init-array
+# initpri3b_LDADD =
# Test --detect-odr-violations
@@ -189,7 +200,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
# Test -o when emitting to a special file (such as something in /dev).
@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_24 = many_sections_test \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ many_sections_r_test initpri1 \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@ initpri2 initpri3a initpri3b \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ initpri2 initpri3a \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile
@GCC_FALSE@many_sections_test_DEPENDENCIES =
@NATIVE_LINKER_FALSE@many_sections_test_DEPENDENCIES =
@@ -204,8 +215,6 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
@NATIVE_LINKER_FALSE@initpri2_DEPENDENCIES =
@GCC_FALSE@initpri3a_DEPENDENCIES =
@NATIVE_LINKER_FALSE@initpri3a_DEPENDENCIES =
-@GCC_FALSE@initpri3b_DEPENDENCIES =
-@NATIVE_LINKER_FALSE@initpri3b_DEPENDENCIES =
# Check that --detect-odr-violations works with compressed debug sections.
@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@am__append_27 = debug_msg_cdebug.err
@@ -306,7 +315,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_3.sh \
@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_4.sh \
@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_6.sh \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_7.sh
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_7.sh \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_final_layout.sh
# Test that symbols known in the IR file but not in the replacement file
# produce an unresolved symbol error.
@@ -318,7 +328,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_6.err \
@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_7.err \
@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_7.syms \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_9.err
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_9.err \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_final_layout.stdout
# Make a copy of two_file_test_1.o, which does not define the symbol _Z4t16av.
@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@am__append_36 = \
@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_1.err \
@@ -467,9 +478,31 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
# Test that --start-lib and --end-lib function correctly.
@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_53 = start_lib_test
+# Test that --gdb-index functions correctly without gcc-generated pubnames.
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@am__append_54 = gdb_index_test_1.sh
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@am__append_55 = gdb_index_test_1.stdout
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@am__append_56 = gdb_index_test_1.stdout gdb_index_test_1
+
+# Test that --gdb-index functions correctly with compressed debug sections.
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@am__append_57 = gdb_index_test_2.sh
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@am__append_58 = gdb_index_test_2.stdout
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@am__append_59 = gdb_index_test_2.stdout gdb_index_test_2
+
+# Another simple C test (DW_AT_high_pc encoding) for --gdb-index.
+
+# Test that --gdb-index functions correctly with gcc-generated pubnames.
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@am__append_60 = gdb_index_test_3.sh \
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@ gdb_index_test_4.sh
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@am__append_61 = gdb_index_test_3.stdout \
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@ gdb_index_test_4.stdout
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@am__append_62 = gdb_index_test_3.stdout \
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@ gdb_index_test_3 \
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@ gdb_index_test_4.stdout \
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@ gdb_index_test_4
+
# Test the --incremental-unchanged flag with an archive library.
# The second link should not update the library.
-@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_54 = incremental_test_2 \
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_63 = incremental_test_2 \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_test_3 \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_test_4 \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_test_5 \
@@ -477,7 +510,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_copy_test \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_common_test_1 \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_comdat_test_1
-@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_55 = two_file_test_tmp_2.o \
+@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_64 = two_file_test_tmp_2.o \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_tmp_3.o \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ incremental_test_4.base \
@DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_test_tmp_4.o \
@@ -487,22 +520,22 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
# These tests work with native and cross linkers.
# Test script section order.
-@NATIVE_OR_CROSS_LINKER_TRUE@am__append_56 = script_test_10.sh
-@NATIVE_OR_CROSS_LINKER_TRUE@am__append_57 = script_test_10.stdout
+@NATIVE_OR_CROSS_LINKER_TRUE@am__append_65 = script_test_10.sh
+@NATIVE_OR_CROSS_LINKER_TRUE@am__append_66 = script_test_10.stdout
# These tests work with cross linkers only.
-@DEFAULT_TARGET_I386_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_58 = split_i386.sh
-@DEFAULT_TARGET_I386_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_59 = split_i386_1.stdout split_i386_2.stdout \
+@DEFAULT_TARGET_I386_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_67 = split_i386.sh
+@DEFAULT_TARGET_I386_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_68 = split_i386_1.stdout split_i386_2.stdout \
@DEFAULT_TARGET_I386_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ split_i386_3.stdout split_i386_4.stdout split_i386_r.stdout
-@DEFAULT_TARGET_I386_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_60 = split_i386_1 split_i386_2 split_i386_3 \
+@DEFAULT_TARGET_I386_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_69 = split_i386_1 split_i386_2 split_i386_3 \
@DEFAULT_TARGET_I386_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ split_i386_4 split_i386_r
-@DEFAULT_TARGET_X86_64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_61 = split_x86_64.sh
-@DEFAULT_TARGET_X86_64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_62 = split_x86_64_1.stdout split_x86_64_2.stdout \
+@DEFAULT_TARGET_X86_64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_70 = split_x86_64.sh
+@DEFAULT_TARGET_X86_64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_71 = split_x86_64_1.stdout split_x86_64_2.stdout \
@DEFAULT_TARGET_X86_64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ split_x86_64_3.stdout split_x86_64_4.stdout split_x86_64_r.stdout
-@DEFAULT_TARGET_X86_64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_63 = split_x86_64_1 split_x86_64_2 split_x86_64_3 \
+@DEFAULT_TARGET_X86_64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_72 = split_x86_64_1 split_x86_64_2 split_x86_64_3 \
@DEFAULT_TARGET_X86_64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ split_x86_64_4 split_x86_64_r
@@ -517,7 +550,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
# Check Thumb to Thumb farcall veneers
# Check Thumb to ARM farcall veneers
-@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_64 = arm_abs_global.sh \
+@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_73 = arm_abs_global.sh \
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_branch_in_range.sh \
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_branch_out_of_range.sh \
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_fix_v4bx.sh \
@@ -531,7 +564,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_farcall_arm_thumb.sh \
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_farcall_thumb_thumb.sh \
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_farcall_thumb_arm.sh
-@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_65 = arm_abs_global.stdout \
+@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_74 = arm_abs_global.stdout \
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_bl_in_range.stdout \
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_bl_out_of_range.stdout \
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ thumb_bl_in_range.stdout \
@@ -576,7 +609,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_farcall_thumb_thumb_6m.stdout \
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_farcall_thumb_arm.stdout \
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_farcall_thumb_arm_5t.stdout
-@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_66 = arm_abs_global \
+@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_75 = arm_abs_global \
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_bl_in_range \
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_bl_out_of_range \
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ thumb_bl_in_range \
@@ -624,6 +657,7 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \
$(top_srcdir)/../config/gettext-sister.m4 \
+ $(top_srcdir)/../config/lcmessage.m4 \
$(top_srcdir)/../config/lead-dot.m4 \
$(top_srcdir)/../config/nls.m4 \
$(top_srcdir)/../config/override.m4 \
@@ -644,7 +678,8 @@ am_libgoldtest_a_OBJECTS = test.$(OBJEXT) testmain.$(OBJEXT) \
testfile.$(OBJEXT)
libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS)
@NATIVE_OR_CROSS_LINKER_TRUE@am__EXEEXT_1 = object_unittest$(EXEEXT) \
-@NATIVE_OR_CROSS_LINKER_TRUE@ binary_unittest$(EXEEXT)
+@NATIVE_OR_CROSS_LINKER_TRUE@ binary_unittest$(EXEEXT) \
+@NATIVE_OR_CROSS_LINKER_TRUE@ leb128_unittest$(EXEEXT)
@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_2 = icf_virtual_function_folding_test$(EXEEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_test$(EXEEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_pic_test$(EXEEXT)
@@ -712,7 +747,6 @@ libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS)
@GCC_TRUE@@NATIVE_LINKER_TRUE@ initpri1$(EXEEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ initpri2$(EXEEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ initpri3a$(EXEEXT) \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@ initpri3b$(EXEEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile$(EXEEXT)
@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_21 = flagstest_compress_debug_sections$(EXEEXT) \
@GCC_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT)
@@ -1200,11 +1234,6 @@ initpri2_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(initpri2_LDFLAGS) \
initpri3a_OBJECTS = $(am_initpri3a_OBJECTS)
initpri3a_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(initpri3a_LDFLAGS) \
$(LDFLAGS) -o $@
-@GCC_TRUE@@NATIVE_LINKER_TRUE@am_initpri3b_OBJECTS = \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@ initpri3.$(OBJEXT)
-initpri3b_OBJECTS = $(am_initpri3b_OBJECTS)
-initpri3b_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(initpri3b_LDFLAGS) \
- $(LDFLAGS) -o $@
@GCC_TRUE@@NATIVE_LINKER_TRUE@am_justsyms_OBJECTS = \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ justsyms_1.$(OBJEXT)
justsyms_OBJECTS = $(am_justsyms_OBJECTS)
@@ -1219,6 +1248,13 @@ justsyms_exec_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
large_OBJECTS = $(am_large_OBJECTS)
large_LINK = $(CCLD) $(large_CFLAGS) $(CFLAGS) $(large_LDFLAGS) \
$(LDFLAGS) -o $@
+@NATIVE_OR_CROSS_LINKER_TRUE@am_leb128_unittest_OBJECTS = \
+@NATIVE_OR_CROSS_LINKER_TRUE@ leb128_unittest.$(OBJEXT)
+leb128_unittest_OBJECTS = $(am_leb128_unittest_OBJECTS)
+leb128_unittest_LDADD = $(LDADD)
+leb128_unittest_DEPENDENCIES = libgoldtest.a ../libgold.a \
+ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
local_labels_test_SOURCES = local_labels_test.c
local_labels_test_OBJECTS = local_labels_test.$(OBJEXT)
local_labels_test_LDADD = $(LDADD)
@@ -1698,8 +1734,9 @@ SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c basic_pie_test.c \
incremental_copy_test.c incremental_test_2.c \
incremental_test_3.c incremental_test_4.c incremental_test_5.c \
incremental_test_6.c $(initpri1_SOURCES) $(initpri2_SOURCES) \
- $(initpri3a_SOURCES) $(initpri3b_SOURCES) $(justsyms_SOURCES) \
- $(justsyms_exec_SOURCES) $(large_SOURCES) local_labels_test.c \
+ $(initpri3a_SOURCES) $(justsyms_SOURCES) \
+ $(justsyms_exec_SOURCES) $(large_SOURCES) \
+ $(leb128_unittest_SOURCES) local_labels_test.c \
many_sections_r_test.c $(many_sections_test_SOURCES) \
$(object_unittest_SOURCES) permission_test.c plugin_test_1.c \
plugin_test_2.c plugin_test_3.c plugin_test_4.c \
@@ -1844,6 +1881,8 @@ EGREP = @EGREP@
EXEEXT = @EXEEXT@
GENCAT = @GENCAT@
GMSGFMT = @GMSGFMT@
+GOLD_LDADD = @GOLD_LDADD@
+GOLD_LDFLAGS = @GOLD_LDFLAGS@
GREP = @GREP@
INCINTL = @INCINTL@
INSTALL = @INSTALL@
@@ -1981,18 +2020,21 @@ TEST_AS = $(top_builddir)/../gas/as-new
MOSTLYCLEANFILES = *.so *.syms *.stdout $(am__append_4) \
$(am__append_17) $(am__append_26) $(am__append_28) \
$(am__append_30) $(am__append_36) $(am__append_40) \
- $(am__append_55) $(am__append_60) $(am__append_63) \
- $(am__append_66)
+ $(am__append_56) $(am__append_59) $(am__append_62) \
+ $(am__append_64) $(am__append_69) $(am__append_72) \
+ $(am__append_75)
# We will add to these later, for each individual test. Note
# that we add each test under check_SCRIPTS or check_PROGRAMS;
# the TESTS variable is automatically populated from these.
check_SCRIPTS = $(am__append_2) $(am__append_34) $(am__append_38) \
- $(am__append_56) $(am__append_58) $(am__append_61) \
- $(am__append_64)
+ $(am__append_54) $(am__append_57) $(am__append_60) \
+ $(am__append_65) $(am__append_67) $(am__append_70) \
+ $(am__append_73)
check_DATA = $(am__append_3) $(am__append_27) $(am__append_29) \
- $(am__append_35) $(am__append_39) $(am__append_57) \
- $(am__append_59) $(am__append_62) $(am__append_65)
+ $(am__append_35) $(am__append_39) $(am__append_55) \
+ $(am__append_58) $(am__append_61) $(am__append_66) \
+ $(am__append_68) $(am__append_71) $(am__append_74)
BUILT_SOURCES = $(am__append_25)
TESTS = $(check_SCRIPTS) $(check_PROGRAMS)
@@ -2010,6 +2052,7 @@ LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL) \
@NATIVE_OR_CROSS_LINKER_TRUE@object_unittest_SOURCES = object_unittest.cc
@NATIVE_OR_CROSS_LINKER_TRUE@binary_unittest_SOURCES = binary_unittest.cc
+@NATIVE_OR_CROSS_LINKER_TRUE@leb128_unittest_SOURCES = leb128_unittest.cc
@GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_test_SOURCES = constructor_test.cc
@GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_test_DEPENDENCIES = gcctestdir/ld
@GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_test_LDFLAGS = -Bgcctestdir/
@@ -2273,16 +2316,12 @@ LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri1_LDADD =
@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri2_SOURCES = initpri2.c
@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri2_DEPENDENCIES = gcctestdir/ld
-@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri2_LDFLAGS = -Bgcctestdir/
+@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri2_LDFLAGS = -Bgcctestdir/ -Wl,--ctors-in-init-array
@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri2_LDADD =
@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri3a_SOURCES = initpri3.c
@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri3a_DEPENDENCIES = gcctestdir/ld
@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri3a_LDFLAGS = -Bgcctestdir/
@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri3a_LDADD =
-@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri3b_SOURCES = initpri3.c
-@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri3b_DEPENDENCIES = gcctestdir/ld
-@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri3b_LDFLAGS = -Bgcctestdir/ -Wl,--no-ctors-in-init-array
-@GCC_TRUE@@NATIVE_LINKER_TRUE@initpri3b_LDADD =
@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_SOURCES = ver_test_main.cc
@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_DEPENDENCIES = gcctestdir/ld ver_test_1.so ver_test_2.so ver_test_4.so
@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,.
@@ -2926,9 +2965,6 @@ initpri2$(EXEEXT): $(initpri2_OBJECTS) $(initpri2_DEPENDENCIES)
initpri3a$(EXEEXT): $(initpri3a_OBJECTS) $(initpri3a_DEPENDENCIES)
@rm -f initpri3a$(EXEEXT)
$(initpri3a_LINK) $(initpri3a_OBJECTS) $(initpri3a_LDADD) $(LIBS)
-initpri3b$(EXEEXT): $(initpri3b_OBJECTS) $(initpri3b_DEPENDENCIES)
- @rm -f initpri3b$(EXEEXT)
- $(initpri3b_LINK) $(initpri3b_OBJECTS) $(initpri3b_LDADD) $(LIBS)
justsyms$(EXEEXT): $(justsyms_OBJECTS) $(justsyms_DEPENDENCIES)
@rm -f justsyms$(EXEEXT)
$(justsyms_LINK) $(justsyms_OBJECTS) $(justsyms_LDADD) $(LIBS)
@@ -2938,6 +2974,9 @@ justsyms_exec$(EXEEXT): $(justsyms_exec_OBJECTS) $(justsyms_exec_DEPENDENCIES)
large$(EXEEXT): $(large_OBJECTS) $(large_DEPENDENCIES)
@rm -f large$(EXEEXT)
$(large_LINK) $(large_OBJECTS) $(large_LDADD) $(LIBS)
+leb128_unittest$(EXEEXT): $(leb128_unittest_OBJECTS) $(leb128_unittest_DEPENDENCIES)
+ @rm -f leb128_unittest$(EXEEXT)
+ $(CXXLINK) $(leb128_unittest_OBJECTS) $(leb128_unittest_LDADD) $(LIBS)
@GCC_FALSE@local_labels_test$(EXEEXT): $(local_labels_test_OBJECTS) $(local_labels_test_DEPENDENCIES)
@GCC_FALSE@ @rm -f local_labels_test$(EXEEXT)
@GCC_FALSE@ $(LINK) $(local_labels_test_OBJECTS) $(local_labels_test_LDADD) $(LIBS)
@@ -3318,6 +3357,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/justsyms_1.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/justsyms_exec.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/large-large.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/leb128_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local_labels_test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/many_sections_r_test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/many_sections_test.Po@am__quote@
@@ -3689,6 +3729,8 @@ plugin_test_6.sh.log: plugin_test_6.sh
@p='plugin_test_6.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
plugin_test_7.sh.log: plugin_test_7.sh
@p='plugin_test_7.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+plugin_final_layout.sh.log: plugin_final_layout.sh
+ @p='plugin_final_layout.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
exclude_libs_test.sh.log: exclude_libs_test.sh
@p='exclude_libs_test.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
discard_locals_test.sh.log: discard_locals_test.sh
@@ -3705,6 +3747,14 @@ dyn_weak_ref.sh.log: dyn_weak_ref.sh
@p='dyn_weak_ref.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
memory_test.sh.log: memory_test.sh
@p='memory_test.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+gdb_index_test_1.sh.log: gdb_index_test_1.sh
+ @p='gdb_index_test_1.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+gdb_index_test_2.sh.log: gdb_index_test_2.sh
+ @p='gdb_index_test_2.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+gdb_index_test_3.sh.log: gdb_index_test_3.sh
+ @p='gdb_index_test_3.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+gdb_index_test_4.sh.log: gdb_index_test_4.sh
+ @p='gdb_index_test_4.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
script_test_10.sh.log: script_test_10.sh
@p='script_test_10.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
split_i386.sh.log: split_i386.sh
@@ -3743,6 +3793,8 @@ object_unittest.log: object_unittest$(EXEEXT)
@p='object_unittest$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
binary_unittest.log: binary_unittest$(EXEEXT)
@p='binary_unittest$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+leb128_unittest.log: leb128_unittest$(EXEEXT)
+ @p='leb128_unittest$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
icf_virtual_function_folding_test.log: icf_virtual_function_folding_test$(EXEEXT)
@p='icf_virtual_function_folding_test$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
basic_test.log: basic_test$(EXEEXT)
@@ -3867,8 +3919,6 @@ initpri2.log: initpri2$(EXEEXT)
@p='initpri2$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
initpri3a.log: initpri3a$(EXEEXT)
@p='initpri3a$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
-initpri3b.log: initpri3b$(EXEEXT)
- @p='initpri3b$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
flagstest_o_specialfile.log: flagstest_o_specialfile$(EXEEXT)
@p='flagstest_o_specialfile$(EXEEXT)'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
flagstest_compress_debug_sections.log: flagstest_compress_debug_sections$(EXEEXT)
@@ -4811,6 +4861,17 @@ uninstall-am:
@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(COMPILE) -c -o $@ $<
@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@unused.c:
@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ @cp /dev/null $@
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_final_layout.o: plugin_final_layout.cc
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -fdata-sections -g -o $@ $<
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_final_layout: plugin_final_layout.o plugin_section_order.so gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--plugin,"./plugin_section_order.so" plugin_final_layout.o
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_final_layout.stdout: plugin_final_layout
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(TEST_NM) -n plugin_final_layout > plugin_final_layout.stdout
+
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_section_order.so: plugin_section_order.o
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(LINK) -Bgcctestdir/ -shared plugin_section_order.o
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_section_order.o: plugin_section_order.c
+@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(COMPILE) -O0 -c -fpic -o $@ $<
@GCC_TRUE@@NATIVE_LINKER_TRUE@exclude_libs_test.syms: exclude_libs_test
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -sW $< >$@ 2>/dev/null
@GCC_TRUE@@NATIVE_LINKER_TRUE@libexclude_libs_test_1.a: exclude_libs_test_1.o
@@ -4880,7 +4941,7 @@ uninstall-am:
# Test STT_GNU_IFUNC symbols.
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmod1.o: ifuncmod1.c
-@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpic -o $@ $<
+@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fPIC -o $@ $<
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmod1.so: ifuncmod1.o gcctestdir/ld
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -shared ifuncmod1.o
@@ -4888,15 +4949,15 @@ uninstall-am:
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -o $@ $<
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain1pic.o: ifuncmain1.c
-@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpic -o $@ $<
+@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fPIC -o $@ $<
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain1pie.o: ifuncmain1.c
-@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpie -o $@ $<
+@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fPIE -o $@ $<
@GCC_TRUE@@HAVE_STATIC_TRUE@@IFUNC_STATIC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain1picstatic: ifuncmain1pic.o ifuncmod1.o gcctestdir/ld
@GCC_TRUE@@HAVE_STATIC_TRUE@@IFUNC_STATIC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -static ifuncmain1pic.o ifuncmod1.o
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain1pic: ifuncmain1pic.o ifuncmod1.so gcctestdir/ld
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ ifuncmain1pic.o ifuncmod1.so -Wl,-R,.
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain1vispic.o: ifuncmain1vis.c
-@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpic -o $@ $<
+@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fPIC -o $@ $<
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain1vispic: ifuncmain1vispic.o ifuncmod1.so gcctestdir/ld
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ ifuncmain1pic.o ifuncmod1.so -Wl,-R,.
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain1staticpic: ifuncmain1pic.o ifuncmod1.o gcctestdir/ld
@@ -4904,40 +4965,40 @@ uninstall-am:
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain1pie: ifuncmain1pie.o ifuncmod1.so gcctestdir/ld
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -pie ifuncmain1pie.o ifuncmod1.so -Wl,-R,.
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain1vispie.o: ifuncmain1vis.c
-@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpie -o $@ $<
+@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fPIE -o $@ $<
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain1vispie: ifuncmain1vispie.o ifuncmod1.so gcctestdir/ld
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -pie ifuncmain1vispie.o ifuncmod1.so -Wl,-R,.
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain1staticpie: ifuncmain1pie.o ifuncmod1.o gcctestdir/ld
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -pie ifuncmain1pie.o ifuncmod1.o
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain2pic.o: ifuncmain2.c
-@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpic -o $@ $<
+@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fPIC -o $@ $<
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncdep2pic.o: ifuncdep2.c
-@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpic -o $@ $<
+@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fPIC -o $@ $<
@GCC_TRUE@@HAVE_STATIC_TRUE@@IFUNC_STATIC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain2picstatic: ifuncmain2pic.o ifuncdep2pic.o gcctestdir/ld
@GCC_TRUE@@HAVE_STATIC_TRUE@@IFUNC_STATIC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -static ifuncmain2pic.o ifuncdep2pic.o
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain2pic: ifuncmain2pic.o ifuncdep2pic.o gcctestdir/ld
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ ifuncmain2pic.o ifuncdep2pic.o
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmod3.o: ifuncmod3.c
-@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpic -o $@ $<
+@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fPIC -o $@ $<
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmod3.so: ifuncmod3.o gcctestdir/ld
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -shared ifuncmod3.o
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain4pic.o: ifuncmain4.c
-@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpic -o $@ $<
+@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fPIC -o $@ $<
@GCC_TRUE@@HAVE_STATIC_TRUE@@IFUNC_STATIC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain4picstatic: ifuncmain4pic.o gcctestdir/ld
@GCC_TRUE@@HAVE_STATIC_TRUE@@IFUNC_STATIC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -static ifuncmain4pic.o
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain5pic.o: ifuncmain5.c
-@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpic -o $@ $<
+@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fPIC -o $@ $<
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain5pie.o: ifuncmain5.c
-@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpie -o $@ $<
+@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fPIE -o $@ $<
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmod5.o: ifuncmod5.c
-@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpic -o $@ $<
+@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fPIC -o $@ $<
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmod5.so: ifuncmod5.o gcctestdir/ld
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -shared ifuncmod5.o
@@ -4953,20 +5014,20 @@ uninstall-am:
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -pie ifuncmain5pie.o ifuncmod5.so -Wl,-R,.
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain6pie.o: ifuncmain6pie.c
-@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpie -o $@ $<
+@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fPIE -o $@ $<
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmod6.o: ifuncmod6.c
-@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpic -o $@ $<
+@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fPIC -o $@ $<
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmod6.so: ifuncmod6.o gcctestdir/ld
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -shared ifuncmod6.o
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain6pie: ifuncmain6pie.o ifuncmod6.so gcctestdir/ld
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -pie ifuncmain6pie.o ifuncmod6.so -Wl,-R,.
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain7pic.o: ifuncmain7.c
-@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpic -o $@ $<
+@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fPIC -o $@ $<
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain7pie.o: ifuncmain7.c
-@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpie -o $@ $<
+@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fPIE -o $@ $<
@GCC_TRUE@@HAVE_STATIC_TRUE@@IFUNC_STATIC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain7picstatic: ifuncmain7pic.o gcctestdir/ld
@GCC_TRUE@@HAVE_STATIC_TRUE@@IFUNC_STATIC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -static ifuncmain7pic.o
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain7pic: ifuncmain7pic.o gcctestdir/ld
@@ -4974,9 +5035,9 @@ uninstall-am:
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncmain7pie: ifuncmain7pie.o gcctestdir/ld
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -pie ifuncmain7pie.o
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncvar1_pic.o: ifuncvar1.c
-@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpic -o $@ $<
+@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fPIC -o $@ $<
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncvar2_pic.o: ifuncvar2.c
-@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fpic -o $@ $<
+@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -fPIC -o $@ $<
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ifuncvar.so: ifuncvar1_pic.o ifuncvar2_pic.o gcctestdir/ld
@GCC_TRUE@@IFUNC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -shared ifuncvar1_pic.o ifuncvar2_pic.o
@GCC_TRUE@@NATIVE_LINKER_TRUE@strong_ref_weak_def_2.o: strong_ref_weak_def_2.c
@@ -5015,6 +5076,30 @@ uninstall-am:
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -nostartfiles -nostdlib -T $(srcdir)/memory_test.t -o $@ memory_test.o
@GCC_TRUE@@NATIVE_LINKER_TRUE@memory_test.stdout: memory_test
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -lWS $< > $@
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@gdb_index_test.o: gdb_index_test.cc
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -g -gno-pubnames -c -o $@ $<
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@gdb_index_test_1: gdb_index_test.o gcctestdir/ld
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--gdb-index $<
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@gdb_index_test_1.stdout: gdb_index_test_1
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) --debug-dump=gdb_index $< > $@
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@gdb_index_test_cdebug.o: gdb_index_test.cc
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -Bgcctestdir/ -O0 -g -Wa,--compress-debug-sections -c -o $@ $<
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@gdb_index_test_2: gdb_index_test_cdebug.o gcctestdir/ld
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--gdb-index $<
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@gdb_index_test_2.stdout: gdb_index_test_2
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@HAVE_ZLIB_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) --debug-dump=gdb_index $< > $@
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@gdb_index_test_3.o: gdb_index_test_3.c
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -O0 -g -c -o $@ $<
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@gdb_index_test_3: gdb_index_test_3.o gcctestdir/ld
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -Wl,--gdb-index,--fatal-warnings $<
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@gdb_index_test_3.stdout: gdb_index_test_3
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) --debug-dump=gdb_index $< > $@
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@gdb_index_test_pub.o: gdb_index_test.cc
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -g -gpubnames -c -o $@ $<
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@gdb_index_test_4: gdb_index_test_pub.o gcctestdir/ld
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--gdb-index $<
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@gdb_index_test_4.stdout: gdb_index_test_4
+@GCC_TRUE@@HAVE_PUBNAMES_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) --debug-dump=gdb_index $< > $@
# End-to-end incremental linking tests.
# Incremental linking is currently supported only on the x86_64 target.
@@ -5436,7 +5521,7 @@ uninstall-am:
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -o $@ $<
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@arm_exidx_test.stdout: arm_exidx_test.so
-@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_READELF) -S $< > $@
+@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_READELF) -Sr $< > $@
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@arm_exidx_test.so: arm_exidx_test.o ../ld-new
@DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ ../ld-new -shared -o $@ $<
diff --git a/binutils-2.22/gold/testsuite/gdb_index_test.cc b/binutils-2.22/gold/testsuite/gdb_index_test.cc
new file mode 100644
index 0000000..342d47c
--- /dev/null
+++ b/binutils-2.22/gold/testsuite/gdb_index_test.cc
@@ -0,0 +1,138 @@
+// gdb_index_test.cc -- a test case for the --gdb-index option.
+
+// Copyright 2012 Free Software Foundation, Inc.
+// Written by Cary Coutant <ccoutant@google.com>.
+
+// This file is part of gold.
+
+// 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.
+
+// This source file defines a number of symbols of different forms
+// to exercise the DWARF scanner in gold.
+
+namespace
+{
+int c1_count;
+int c2_count;
+};
+
+namespace one
+{
+
+enum G
+{
+ G_A,
+ G_B,
+ G_C
+};
+
+class c1
+{
+ public:
+ static int count;
+
+ c1()
+ { ++c1_count; }
+
+ ~c1()
+ {
+ --c1_count;
+ }
+
+ enum E
+ {
+ E_A,
+ E_B,
+ E_C,
+ };
+
+ int
+ val()
+ { return E_A; }
+};
+
+c1 c1v;
+};
+
+namespace two
+{
+const int ci = 3;
+
+template <typename T>
+class c2
+{
+ public:
+ c2(T t)
+ : t_(t)
+ {
+ ++c2_count;
+ }
+
+ ~c2()
+ { --c2_count; }
+
+ T
+ val()
+ { return this->t_; }
+
+ T t_;
+};
+
+c2<int> c2v1(1);
+c2<double> c2v2(2.0);
+c2<int const*> c2v3(&ci);
+};
+
+enum F
+{
+ F_A,
+ F_B,
+ F_C
+};
+
+template <class C>
+bool
+check(C* c)
+{ return c->val() == 0; }
+
+bool
+check_enum(int i)
+{ return i > 0; }
+
+struct anonymous_union_container {
+ union {
+ struct astruct {
+ int a;
+ };
+ int b;
+ } u;
+};
+
+anonymous_union_container anonymous_union_var;
+
+int
+main()
+{
+ F f = F_A;
+ one::G g = one::G_A;
+ check_enum(f);
+ check_enum(g);
+ check(&one::c1v);
+ check(&two::c2v1);
+ check(&two::c2v2);
+ check(&two::c2v3);
+ return anonymous_union_var.u.b;
+}
diff --git a/binutils-2.22/gold/testsuite/gdb_index_test_1.sh b/binutils-2.22/gold/testsuite/gdb_index_test_1.sh
new file mode 100755
index 0000000..f04c8a7
--- /dev/null
+++ b/binutils-2.22/gold/testsuite/gdb_index_test_1.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# gdb_index_test_1.sh -- a test case for the --gdb-index option.
+
+# Copyright 2012 Free Software Foundation, Inc.
+# Written by Cary Coutant <ccoutant@google.com>.
+
+# This file is part of gold.
+
+# 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.
+
+exec ${srcdir}/gdb_index_test_comm.sh gdb_index_test_1.stdout
diff --git a/binutils-2.22/gold/testsuite/gdb_index_test_2.sh b/binutils-2.22/gold/testsuite/gdb_index_test_2.sh
new file mode 100755
index 0000000..e31aa42
--- /dev/null
+++ b/binutils-2.22/gold/testsuite/gdb_index_test_2.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# gdb_index_test_2.sh -- a test case for the --gdb-index option.
+
+# Copyright 2012 Free Software Foundation, Inc.
+# Written by Cary Coutant <ccoutant@google.com>.
+
+# This file is part of gold.
+
+# 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.
+
+exec ${srcdir}/gdb_index_test_comm.sh gdb_index_test_2.stdout
diff --git a/binutils-2.22/gold/testsuite/gdb_index_test_3.c b/binutils-2.22/gold/testsuite/gdb_index_test_3.c
new file mode 100644
index 0000000..df49261
--- /dev/null
+++ b/binutils-2.22/gold/testsuite/gdb_index_test_3.c
@@ -0,0 +1,39 @@
+// gdb_index_test.c -- a test case for the --gdb-index option.
+
+// Copyright 2012 Free Software Foundation, Inc.
+
+// This file is part of gold.
+
+// 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.
+
+// This source file is just a simple C source file that is mainly to
+// test the CU DW_AT_high_pc FORM encoding is handled correctly by the
+// DWARF scanner in gold.
+
+int check_int (int);
+int main (void);
+
+int j = 0;
+
+int
+check_int (int i)
+{ return i > 0; }
+
+int
+main()
+{
+ return check_int (0);
+}
diff --git a/binutils-2.22/gold/testsuite/gdb_index_test_3.sh b/binutils-2.22/gold/testsuite/gdb_index_test_3.sh
new file mode 100755
index 0000000..bd1500b
--- /dev/null
+++ b/binutils-2.22/gold/testsuite/gdb_index_test_3.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+# gdb_index_test_3.sh -- a test case for the --gdb-index option.
+
+# Copyright 2012 Free Software Foundation, Inc.
+# Written by Cary Coutant <ccoutant@google.com>.
+
+# This file is part of gold.
+
+# 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.
+
+check()
+{
+ if ! grep -q "$2" "$1"
+ then
+ echo "Did not find expected output:"
+ echo " $2"
+ echo ""
+ echo "Actual error output below:"
+ cat "$1"
+ exit 1
+ fi
+}
+
+STDOUT=gdb_index_test_3.stdout
+
+check $STDOUT "^Version [45]"
+
+# Look for the symbols we know should be in the symbol table.
+
+check $STDOUT "^\[ *[0-9]*\] main:"
+check $STDOUT "^\[ *[0-9]*\] check_int:"
+check $STDOUT "^\[ *[0-9]*\] j:"
+check $STDOUT "^\[ *[0-9]*\] int:"
+
+exit 0
diff --git a/binutils-2.22/gold/testsuite/gdb_index_test_4.sh b/binutils-2.22/gold/testsuite/gdb_index_test_4.sh
new file mode 100755
index 0000000..44c8a9a
--- /dev/null
+++ b/binutils-2.22/gold/testsuite/gdb_index_test_4.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# gdb_index_test_4.sh -- a test case for the --gdb-index option.
+
+# Copyright 2012 Free Software Foundation, Inc.
+# Written by Cary Coutant <ccoutant@google.com>.
+
+# This file is part of gold.
+
+# 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.
+
+exec ${srcdir}/gdb_index_test_comm.sh gdb_index_test_4.stdout
diff --git a/binutils-2.22/gold/testsuite/gdb_index_test_comm.sh b/binutils-2.22/gold/testsuite/gdb_index_test_comm.sh
new file mode 100755
index 0000000..7100329
--- /dev/null
+++ b/binutils-2.22/gold/testsuite/gdb_index_test_comm.sh
@@ -0,0 +1,84 @@
+#!/bin/sh
+
+# gdb_index_test_comm.sh -- common code for --gdb-index tests.
+
+# Copyright 2012 Free Software Foundation, Inc.
+# Written by Cary Coutant <ccoutant@google.com>.
+
+# This file is part of gold.
+
+# 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.
+
+check()
+{
+ if ! grep -q "$2" "$1"
+ then
+ echo "Did not find expected output:"
+ echo " $2"
+ echo ""
+ echo "Actual error output below:"
+ cat "$1"
+ exit 1
+ fi
+}
+
+STDOUT="$1"
+
+check $STDOUT "^Version [45]"
+
+# Look for the symbols we know should be in the symbol table.
+
+check $STDOUT "^\[ *[0-9]*\] (anonymous namespace):"
+check $STDOUT "^\[ *[0-9]*\] (anonymous namespace)::c1_count:"
+check $STDOUT "^\[ *[0-9]*\] (anonymous namespace)::c2_count:"
+check $STDOUT "^\[ *[0-9]*\] bool:"
+check $STDOUT "^\[ *[0-9]*\] check<one::c1>:"
+check $STDOUT "^\[ *[0-9]*\] check<two::c2<double> >:"
+check $STDOUT "^\[ *[0-9]*\] check<two::c2<int> >:"
+# check $STDOUT "^\[ *[0-9]*\] check<two::c2<int const\*> >:"
+check $STDOUT "^\[ *[0-9]*\] double:"
+check $STDOUT "^\[ *[0-9]*\] F_A:"
+check $STDOUT "^\[ *[0-9]*\] F_B:"
+check $STDOUT "^\[ *[0-9]*\] F_C:"
+check $STDOUT "^\[ *[0-9]*\] int:"
+check $STDOUT "^\[ *[0-9]*\] main:"
+check $STDOUT "^\[ *[0-9]*\] one:"
+check $STDOUT "^\[ *[0-9]*\] one::c1:"
+check $STDOUT "^\[ *[0-9]*\] one::c1::~c1:"
+check $STDOUT "^\[ *[0-9]*\] one::c1::c1:"
+check $STDOUT "^\[ *[0-9]*\] one::c1::val:"
+check $STDOUT "^\[ *[0-9]*\] one::c1v:"
+check $STDOUT "^\[ *[0-9]*\] one::G_A:"
+check $STDOUT "^\[ *[0-9]*\] one::G_B:"
+check $STDOUT "^\[ *[0-9]*\] one::G_B:"
+check $STDOUT "^\[ *[0-9]*\] two:"
+check $STDOUT "^\[ *[0-9]*\] two::c2<double>::~c2:"
+check $STDOUT "^\[ *[0-9]*\] two::c2<double>::c2:"
+check $STDOUT "^\[ *[0-9]*\] two::c2<double>::val:"
+check $STDOUT "^\[ *[0-9]*\] two::c2<double>:"
+check $STDOUT "^\[ *[0-9]*\] two::c2<int const\*>:"
+check $STDOUT "^\[ *[0-9]*\] two::c2<int const\*>::~c2:"
+check $STDOUT "^\[ *[0-9]*\] two::c2<int const\*>::c2:"
+check $STDOUT "^\[ *[0-9]*\] two::c2<int const\*>::val:"
+check $STDOUT "^\[ *[0-9]*\] two::c2<int>::~c2:"
+check $STDOUT "^\[ *[0-9]*\] two::c2<int>::c2:"
+check $STDOUT "^\[ *[0-9]*\] two::c2<int>::val:"
+check $STDOUT "^\[ *[0-9]*\] two::c2<int>:"
+check $STDOUT "^\[ *[0-9]*\] two::c2v1:"
+check $STDOUT "^\[ *[0-9]*\] two::c2v2:"
+check $STDOUT "^\[ *[0-9]*\] anonymous_union_var:"
+
+exit 0
diff --git a/binutils-2.22/gold/testsuite/leb128_unittest.cc b/binutils-2.22/gold/testsuite/leb128_unittest.cc
new file mode 100644
index 0000000..05c7093
--- /dev/null
+++ b/binutils-2.22/gold/testsuite/leb128_unittest.cc
@@ -0,0 +1,88 @@
+// leb_unittest.cc -- test read_signed_LEB_128 and read_unsigned_LEB_128
+
+// Copyright 2012 Free Software Foundation, Inc.
+// Written by Cary Coutant <ccoutant@google.com>.
+
+// This file is part of gold.
+
+// 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.
+
+#include "gold.h"
+
+#include <sys/types.h>
+
+#include "int_encoding.h"
+
+#include "test.h"
+
+namespace gold_testsuite
+{
+
+using namespace gold;
+
+bool
+Leb128_test(Test_report*)
+{
+ size_t len;
+
+ // Unsigned tests.
+ static unsigned char u1[] = { 0 }; // 0
+ static unsigned char u2[] = { 1 }; // 1
+ static unsigned char u3[] = { 126 }; // 126
+ static unsigned char u4[] = { 127 }; // 127
+ static unsigned char u5[] = { 0x80+0, 1 }; // 128
+ static unsigned char u6[] = { 0x80+1, 1 }; // 129
+ static unsigned char u7[] = { 0x80+57, 100 }; // 12857
+ static unsigned char u8[] = { 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x80,
+ 0x80, 1}; // 1ULL << 63
+
+ // Signed tests.
+ static unsigned char s1[] = { 0 }; // 0
+ static unsigned char s2[] = { 1 }; // 1
+ static unsigned char s3[] = { 0x7e }; // -2
+ static unsigned char s4[] = { 0x80+127, 0 }; // 127
+ static unsigned char s5[] = { 0x80+1, 0x7f }; // -127
+ static unsigned char s6[] = { 0x80+0, 1 }; // 128
+ static unsigned char s7[] = { 0x80+0, 0x7f }; // -128
+ static unsigned char s8[] = { 0x80+1, 1 }; // 129
+ static unsigned char s9[] = { 0xff, 0x7e }; // -129
+
+ CHECK(read_unsigned_LEB_128(u1, &len) == 0 && len == sizeof(u1));
+ CHECK(read_unsigned_LEB_128(u2, &len) == 1 && len == sizeof(u2));
+ CHECK(read_unsigned_LEB_128(u3, &len) == 126 && len == sizeof(u3));
+ CHECK(read_unsigned_LEB_128(u4, &len) == 127 && len == sizeof(u4));
+ CHECK(read_unsigned_LEB_128(u5, &len) == 128 && len == sizeof(u5));
+ CHECK(read_unsigned_LEB_128(u6, &len) == 129 && len == sizeof(u6));
+ CHECK(read_unsigned_LEB_128(u7, &len) == 12857 && len == sizeof(u7));
+ CHECK(read_unsigned_LEB_128(u8, &len) == (1ULL << 63) && len == sizeof(u8));
+
+ CHECK(read_signed_LEB_128(s1, &len) == 0 && len == sizeof(s1));
+ CHECK(read_signed_LEB_128(s2, &len) == 1 && len == sizeof(s2));
+ CHECK(read_signed_LEB_128(s3, &len) == -2 && len == sizeof(s3));
+ CHECK(read_signed_LEB_128(s4, &len) == 127 && len == sizeof(s4));
+ CHECK(read_signed_LEB_128(s5, &len) == -127 && len == sizeof(s5));
+ CHECK(read_signed_LEB_128(s6, &len) == 128 && len == sizeof(s6));
+ CHECK(read_signed_LEB_128(s7, &len) == -128 && len == sizeof(s7));
+ CHECK(read_signed_LEB_128(s8, &len) == 129 && len == sizeof(s8));
+ CHECK(read_signed_LEB_128(s9, &len) == -129 && len == sizeof(s9));
+
+ return true;
+}
+
+Register_test leb128_register("LEB128", Leb128_test);
+
+} // End namespace gold_testsuite.
diff --git a/binutils-2.22/gold/testsuite/plugin_final_layout.cc b/binutils-2.22/gold/testsuite/plugin_final_layout.cc
new file mode 100644
index 0000000..3e264f6
--- /dev/null
+++ b/binutils-2.22/gold/testsuite/plugin_final_layout.cc
@@ -0,0 +1,41 @@
+// plugin_final_layout.cc -- a test case for gold
+
+// Copyright 2011 Free Software Foundation, Inc.
+// Written by Sriraman Tallam <tmsriram@google.com>.
+
+// This file is part of gold.
+
+// 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.
+
+// The goal of this program is to verify if section ordering
+// via plugins happens correctly.
+
+void bar ()
+{
+}
+
+void baz ()
+{
+}
+
+void foo ()
+{
+}
+
+int main ()
+{
+ return 0;
+}
diff --git a/binutils-2.22/gold/testsuite/plugin_final_layout.sh b/binutils-2.22/gold/testsuite/plugin_final_layout.sh
new file mode 100755
index 0000000..600f8e2
--- /dev/null
+++ b/binutils-2.22/gold/testsuite/plugin_final_layout.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+# plugin_final_layout.sh -- test
+
+# Copyright 2011 Free Software Foundation, Inc.
+# Written by Sriraman Tallam <tmsriram@google.com>.
+
+# This file is part of gold.
+
+# 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.
+
+# The goal of this program is to verify if --section-ordering-file works as
+# intended. File final_layout.cc is in this test.
+
+
+set -e
+
+check()
+{
+ awk "
+BEGIN { saw1 = 0; saw2 = 0; err = 0; }
+/.*$2\$/ { saw1 = 1; }
+/.*$3\$/ {
+ saw2 = 1;
+ if (!saw1)
+ {
+ printf \"layout of $2 and $3 is not right\\n\";
+ err = 1;
+ exit 1;
+ }
+ }
+END {
+ if (!saw1 && !err)
+ {
+ printf \"did not see $2\\n\";
+ exit 1;
+ }
+ if (!saw2 && !err)
+ {
+ printf \"did not see $3\\n\";
+ exit 1;
+ }
+ }" $1
+}
+
+check plugin_final_layout.stdout "_Z3foov" "_Z3barv"
+check plugin_final_layout.stdout "_Z3barv" "_Z3bazv"
diff --git a/binutils-2.22/gold/testsuite/plugin_section_order.c b/binutils-2.22/gold/testsuite/plugin_section_order.c
new file mode 100644
index 0000000..0e2079b
--- /dev/null
+++ b/binutils-2.22/gold/testsuite/plugin_section_order.c
@@ -0,0 +1,167 @@
+/* plugin_section_reorder.c -- Simple plugin to reorder function sections
+
+ Copyright 2011 Free Software Foundation, Inc.
+ Written by Sriraman Tallam <tmsriram@google.com>.
+
+ This file is part of gold.
+
+ 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. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "plugin-api.h"
+
+static ld_plugin_get_input_section_count get_input_section_count = NULL;
+static ld_plugin_get_input_section_type get_input_section_type = NULL;
+static ld_plugin_get_input_section_name get_input_section_name = NULL;
+static ld_plugin_get_input_section_contents get_input_section_contents = NULL;
+static ld_plugin_update_section_order update_section_order = NULL;
+static ld_plugin_allow_section_ordering allow_section_ordering = NULL;
+
+enum ld_plugin_status onload(struct ld_plugin_tv *tv);
+enum ld_plugin_status claim_file_hook(const struct ld_plugin_input_file *file,
+ int *claimed);
+enum ld_plugin_status all_symbols_read_hook(void);
+
+/* Plugin entry point. */
+enum ld_plugin_status
+onload(struct ld_plugin_tv *tv)
+{
+ struct ld_plugin_tv *entry;
+ for (entry = tv; entry->tv_tag != LDPT_NULL; ++entry)
+ {
+ switch (entry->tv_tag)
+ {
+ case LDPT_REGISTER_CLAIM_FILE_HOOK:
+ assert((*entry->tv_u.tv_register_claim_file) (claim_file_hook) == LDPS_OK);
+ break;
+ case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
+ assert((*entry->tv_u.tv_register_all_symbols_read) (all_symbols_read_hook)
+ == LDPS_OK);
+ break;
+ case LDPT_GET_INPUT_SECTION_COUNT:
+ get_input_section_count = *entry->tv_u.tv_get_input_section_count;
+ break;
+ case LDPT_GET_INPUT_SECTION_TYPE:
+ get_input_section_type = *entry->tv_u.tv_get_input_section_type;
+ break;
+ case LDPT_GET_INPUT_SECTION_NAME:
+ get_input_section_name = *entry->tv_u.tv_get_input_section_name;
+ break;
+ case LDPT_GET_INPUT_SECTION_CONTENTS:
+ get_input_section_contents = *entry->tv_u.tv_get_input_section_contents;
+ break;
+ case LDPT_UPDATE_SECTION_ORDER:
+ update_section_order = *entry->tv_u.tv_update_section_order;
+ break;
+ case LDPT_ALLOW_SECTION_ORDERING:
+ allow_section_ordering = *entry->tv_u.tv_allow_section_ordering;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (get_input_section_count == NULL
+ || get_input_section_type == NULL
+ || get_input_section_name == NULL
+ || get_input_section_contents == NULL
+ || update_section_order == NULL
+ || allow_section_ordering == NULL)
+ {
+ fprintf(stderr, "Some interfaces are missing\n");
+ return LDPS_ERR;
+ }
+
+ return LDPS_OK;
+}
+
+inline static int is_prefix_of(const char *prefix, const char *str)
+{
+ return strncmp(prefix, str, strlen (prefix)) == 0;
+}
+
+struct ld_plugin_section section_list[3];
+int num_entries = 0;
+
+/* This function is called by the linker for every new object it encounters. */
+enum ld_plugin_status
+claim_file_hook(const struct ld_plugin_input_file *file, int *claimed)
+{
+ static int is_ordering_specified = 0;
+ struct ld_plugin_section section;
+ unsigned int count = 0;
+ unsigned int shndx;
+
+ *claimed = 0;
+ if (is_ordering_specified == 0)
+ {
+ /* Inform the linker to prepare for section reordering. */
+ (*allow_section_ordering)();
+ is_ordering_specified = 1;
+ }
+
+ (*get_input_section_count)(file->handle, &count);
+
+ for (shndx = 0; shndx < count; ++shndx)
+ {
+ char *name = NULL;
+ int position = 3;
+
+ section.handle = file->handle;
+ section.shndx = shndx;
+ (*get_input_section_name)(section, &name);
+
+ /* Order is foo() followed by bar() followed by baz() */
+ if (is_prefix_of(".text.", name))
+ {
+ if (strstr(name, "_Z3foov") != NULL)
+ position = 0;
+ else if (strstr(name, "_Z3barv") != NULL)
+ position = 1;
+ else if (strstr(name, "_Z3bazv") != NULL)
+ position = 2;
+ else
+ position = 3;
+ }
+ if (position < 3)
+ {
+ section_list[position].handle = file->handle;
+ section_list[position].shndx = shndx;
+ num_entries++;
+ }
+ }
+ return LDPS_OK;
+}
+
+/* This function is called by the linker after all the symbols have been read.
+ At this stage, it is fine to tell the linker the desired function order. */
+
+enum ld_plugin_status
+all_symbols_read_hook(void)
+{
+ if (num_entries == 3)
+ update_section_order(section_list, num_entries);
+
+ return LDPS_OK;
+}
+
diff --git a/binutils-2.22/gold/testsuite/plugin_test_2.sh b/binutils-2.22/gold/testsuite/plugin_test_2.sh
index a47d22a..293b1f0 100755
--- a/binutils-2.22/gold/testsuite/plugin_test_2.sh
+++ b/binutils-2.22/gold/testsuite/plugin_test_2.sh
@@ -45,7 +45,7 @@ check plugin_test_2.err "two_file_test_main.o: claim file hook called"
check plugin_test_2.err "two_file_test_1.syms: claim file hook called"
check plugin_test_2.err "two_file_test_1b.syms: claim file hook called"
check plugin_test_2.err "two_file_shared_2.so: claim file hook called"
-check plugin_test_2.err "two_file_test_1.syms: _Z4f13iv: PREVAILING_DEF_REG"
+check plugin_test_2.err "two_file_test_1.syms: _Z4f13iv: PREVAILING_DEF_IRONLY_EXP"
check plugin_test_2.err "two_file_test_1.syms: _Z2t2v: PREVAILING_DEF_REG"
check plugin_test_2.err "two_file_test_1.syms: v2: RESOLVED_DYN"
check plugin_test_2.err "two_file_test_1.syms: t17data: RESOLVED_DYN"
diff --git a/binutils-2.22/gold/testsuite/relro_test.cc b/binutils-2.22/gold/testsuite/relro_test.cc
index d741022..795ad39 100644
--- a/binutils-2.22/gold/testsuite/relro_test.cc
+++ b/binutils-2.22/gold/testsuite/relro_test.cc
@@ -45,6 +45,9 @@ int* const p1 __attribute__ ((aligned(64))) = &i1;
// P2 is a local relro variable.
int* const p2 __attribute__ ((aligned(64))) = &i2;
+// Add a TLS variable to make sure -z relro works correctly with TLS.
+__thread int i3 = 1;
+
// Test symbol addresses.
bool
@@ -76,6 +79,7 @@ t1()
assert(i1page != p2page);
assert(i2page != p1page);
assert(i2page != p2page);
+ assert(i3 == 1);
return true;
}
diff --git a/binutils-2.22/gold/testsuite/script_test_2.t b/binutils-2.22/gold/testsuite/script_test_2.t
index 73d39df..6a0188f 100644
--- a/binutils-2.22/gold/testsuite/script_test_2.t
+++ b/binutils-2.22/gold/testsuite/script_test_2.t
@@ -49,7 +49,7 @@ SECTIONS
/* This should match the remaining sections. */
*(.gold_test)
- . = . + 4;
+ . = 60;
start_data = .;
BYTE(1)
SHORT(2)
diff --git a/binutils-2.22/gold/testsuite/testfile.cc b/binutils-2.22/gold/testsuite/testfile.cc
index 93e716a..e963d4d 100644
--- a/binutils-2.22/gold/testsuite/testfile.cc
+++ b/binutils-2.22/gold/testsuite/testfile.cc
@@ -1,6 +1,6 @@
// testfile.cc -- Dummy ELF objects for testing purposes.
-// Copyright 2006, 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2011, 2012 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -100,6 +100,8 @@ const Target::Target_info Target_test<size, big_endian>::test_target_info =
0x08000000, // default_text_segment_address
0x1000, // abi_pagesize
0x1000, // common_pagesize
+ false, // isolate_execinstr
+ 0, // rosegment_gap
elfcpp::SHN_UNDEF, // small_common_shndx
elfcpp::SHN_UNDEF, // large_common_shndx
0, // small_common_section_flags
@@ -154,15 +156,15 @@ class Target_selector_test : public Target_selector
: Target_selector(0xffff, size, big_endian, NULL, NULL)
{ }
- Target*
+ virtual Target*
do_instantiate_target()
{
gold_unreachable();
return NULL;
}
- Target*
- do_recognize(int, int, int)
+ virtual Target*
+ do_recognize(Input_file*, off_t, int, int, int)
{
if (size == 32)
{
@@ -198,11 +200,11 @@ class Target_selector_test : public Target_selector
return NULL;
}
- Target*
+ virtual Target*
do_recognize_by_name(const char*)
{ return NULL; }
- void
+ virtual void
do_supported_names(std::vector<const char*>*)
{ }
};
diff --git a/binutils-2.22/gold/testsuite/tls_test.cc b/binutils-2.22/gold/testsuite/tls_test.cc
index 880bf23..c875752 100644
--- a/binutils-2.22/gold/testsuite/tls_test.cc
+++ b/binutils-2.22/gold/testsuite/tls_test.cc
@@ -44,8 +44,8 @@
// last Verify that the above tests left the variables set correctly.
-#include <cstdio>
#include "config.h"
+#include <cstdio>
#include "tls_test.h"
#define CHECK_EQ_OR_RETURN(var, expected) \
diff --git a/binutils-2.22/gold/testsuite/tls_test_c.c b/binutils-2.22/gold/testsuite/tls_test_c.c
index 730e46d..896191f 100644
--- a/binutils-2.22/gold/testsuite/tls_test_c.c
+++ b/binutils-2.22/gold/testsuite/tls_test_c.c
@@ -23,8 +23,8 @@
/* The only way I know to get gcc to generate a TLS common symbol is
to use a C file and an OpenMP directive. */
-#include <stdio.h>
#include "config.h"
+#include <stdio.h>
#define CHECK_EQ_OR_RETURN(var, expected) \
do \
diff --git a/binutils-2.22/gold/timer.cc b/binutils-2.22/gold/timer.cc
index d9b8874..f3a1c91 100644
--- a/binutils-2.22/gold/timer.cc
+++ b/binutils-2.22/gold/timer.cc
@@ -22,6 +22,8 @@
#include "gold.h"
+#include <unistd.h>
+
#ifdef HAVE_TIMES
#include <sys/times.h>
#endif
@@ -49,6 +51,15 @@ Timer::start()
this->get_time(&this->start_time_);
}
+// Record the time used by pass N (0 <= N <= 2).
+void
+Timer::stamp(int n)
+{
+ gold_assert(n >= 0 && n <= 2);
+ TimeStats& thispass = this->pass_times_[n];
+ this->get_time(&thispass);
+}
+
#if HAVE_SYSCONF && defined _SC_CLK_TCK
# define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
#else
@@ -106,4 +117,17 @@ Timer::get_elapsed_time()
return delta;
}
+// Return the stats for pass N (0 <= N <= 2).
+Timer::TimeStats
+Timer::get_pass_time(int n)
+{
+ gold_assert(n >= 0 && n <= 2);
+ TimeStats thispass = this->pass_times_[n];
+ TimeStats& lastpass = n > 0 ? this->pass_times_[n-1] : this->start_time_;
+ thispass.wall -= lastpass.wall;
+ thispass.user -= lastpass.user;
+ thispass.sys -= lastpass.sys;
+ return thispass;
+}
+
}
diff --git a/binutils-2.22/gold/timer.h b/binutils-2.22/gold/timer.h
index 50b55e4..4f986ca 100644
--- a/binutils-2.22/gold/timer.h
+++ b/binutils-2.22/gold/timer.h
@@ -48,10 +48,18 @@ class Timer
TimeStats
get_elapsed_time();
+ // Return the stats for pass N (0 <= N <= 2).
+ TimeStats
+ get_pass_time(int n);
+
// Start counting the time.
void
start();
+ // Record the time used by pass N (0 <= N <= 2).
+ void
+ stamp(int n);
+
private:
// This class cannot be copied.
Timer(const Timer&);
@@ -63,6 +71,9 @@ class Timer
// The time of the last call to start.
TimeStats start_time_;
+
+ // Times for each pass.
+ TimeStats pass_times_[3];
};
}
diff --git a/binutils-2.22/gold/x86_64.cc b/binutils-2.22/gold/x86_64.cc
index 45b7c60..2ac29bf 100644
--- a/binutils-2.22/gold/x86_64.cc
+++ b/binutils-2.22/gold/x86_64.cc
@@ -1,6 +1,7 @@
// x86_64.cc -- x86_64 target support for gold.
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012
+// Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -39,6 +40,7 @@
#include "target-select.h"
#include "tls.h"
#include "freebsd.h"
+#include "nacl.h"
#include "gc.h"
#include "icf.h"
@@ -48,26 +50,33 @@ namespace
using namespace gold;
// A class to handle the PLT data.
+// This is an abstract base class that handles most of the linker details
+// but does not know the actual contents of PLT entries. The derived
+// classes below fill in those details.
+template<int size>
class Output_data_plt_x86_64 : public Output_section_data
{
public:
- typedef Output_data_reloc<elfcpp::SHT_RELA, true, 64, false> Reloc_section;
+ typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, false> Reloc_section;
- Output_data_plt_x86_64(Layout* layout, Output_data_got<64, false>* got,
+ Output_data_plt_x86_64(Layout* layout, uint64_t addralign,
+ Output_data_got<64, false>* got,
Output_data_space* got_plt,
Output_data_space* got_irelative)
- : Output_section_data(16), layout_(layout), tlsdesc_rel_(NULL),
+ : Output_section_data(addralign), layout_(layout), tlsdesc_rel_(NULL),
irelative_rel_(NULL), got_(got), got_plt_(got_plt),
got_irelative_(got_irelative), count_(0), irelative_count_(0),
tlsdesc_got_offset_(-1U), free_list_()
{ this->init(layout); }
- Output_data_plt_x86_64(Layout* layout, Output_data_got<64, false>* got,
+ Output_data_plt_x86_64(Layout* layout, uint64_t plt_entry_size,
+ Output_data_got<64, false>* got,
Output_data_space* got_plt,
Output_data_space* got_irelative,
unsigned int plt_count)
- : Output_section_data((plt_count + 1) * plt_entry_size, 16, false),
+ : Output_section_data((plt_count + 1) * plt_entry_size,
+ plt_entry_size, false),
layout_(layout), tlsdesc_rel_(NULL), irelative_rel_(NULL), got_(got),
got_plt_(got_plt), got_irelative_(got_irelative), count_(plt_count),
irelative_count_(0), tlsdesc_got_offset_(-1U), free_list_()
@@ -90,7 +99,7 @@ class Output_data_plt_x86_64 : public Output_section_data
// Add an entry to the PLT for a local STT_GNU_IFUNC symbol.
unsigned int
add_local_ifunc_entry(Symbol_table* symtab, Layout*,
- Sized_relobj_file<64, false>* relobj,
+ Sized_relobj_file<size, false>* relobj,
unsigned int local_sym_index);
// Add the relocation for a PLT entry.
@@ -116,7 +125,10 @@ class Output_data_plt_x86_64 : public Output_section_data
// Return the offset of the reserved TLSDESC_PLT entry.
unsigned int
get_tlsdesc_plt_offset() const
- { return (this->count_ + this->irelative_count_ + 1) * plt_entry_size; }
+ {
+ return ((this->count_ + this->irelative_count_ + 1)
+ * this->get_plt_entry_size());
+ }
// Return the .rela.plt section data.
Reloc_section*
@@ -143,21 +155,21 @@ class Output_data_plt_x86_64 : public Output_section_data
{ return this->count_ + this->irelative_count_; }
// Return the offset of the first non-reserved PLT entry.
- static unsigned int
+ unsigned int
first_plt_entry_offset()
- { return plt_entry_size; }
+ { return this->get_plt_entry_size(); }
// Return the size of a PLT entry.
- static unsigned int
- get_plt_entry_size()
- { return plt_entry_size; }
+ unsigned int
+ get_plt_entry_size() const
+ { return this->do_get_plt_entry_size(); }
// Reserve a slot in the PLT for an existing symbol in an incremental update.
void
reserve_slot(unsigned int plt_index)
{
- this->free_list_.remove((plt_index + 1) * plt_entry_size,
- (plt_index + 2) * plt_entry_size);
+ this->free_list_.remove((plt_index + 1) * this->get_plt_entry_size(),
+ (plt_index + 2) * this->get_plt_entry_size());
}
// Return the PLT address to use for a global symbol.
@@ -168,7 +180,74 @@ class Output_data_plt_x86_64 : public Output_section_data
uint64_t
address_for_local(const Relobj*, unsigned int symndx);
+ // Add .eh_frame information for the PLT.
+ void
+ add_eh_frame(Layout* layout)
+ { this->do_add_eh_frame(layout); }
+
protected:
+ // Fill in the first PLT entry.
+ void
+ fill_first_plt_entry(unsigned char* pov,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_address)
+ { this->do_fill_first_plt_entry(pov, got_address, plt_address); }
+
+ // Fill in a normal PLT entry. Returns the offset into the entry that
+ // should be the initial GOT slot value.
+ unsigned int
+ fill_plt_entry(unsigned char* pov,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+ unsigned int got_offset,
+ unsigned int plt_offset,
+ unsigned int plt_index)
+ {
+ return this->do_fill_plt_entry(pov, got_address, plt_address,
+ got_offset, plt_offset, plt_index);
+ }
+
+ // Fill in the reserved TLSDESC PLT entry.
+ void
+ fill_tlsdesc_entry(unsigned char* pov,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_base,
+ unsigned int tlsdesc_got_offset,
+ unsigned int plt_offset)
+ {
+ this->do_fill_tlsdesc_entry(pov, got_address, plt_address, got_base,
+ tlsdesc_got_offset, plt_offset);
+ }
+
+ virtual unsigned int
+ do_get_plt_entry_size() const = 0;
+
+ virtual void
+ do_fill_first_plt_entry(unsigned char* pov,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_addr,
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_addr)
+ = 0;
+
+ virtual unsigned int
+ do_fill_plt_entry(unsigned char* pov,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+ unsigned int got_offset,
+ unsigned int plt_offset,
+ unsigned int plt_index) = 0;
+
+ virtual void
+ do_fill_tlsdesc_entry(unsigned char* pov,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_base,
+ unsigned int tlsdesc_got_offset,
+ unsigned int plt_offset) = 0;
+
+ virtual void
+ do_add_eh_frame(Layout* layout) = 0;
+
void
do_adjust_output_section(Output_section* os);
@@ -177,27 +256,11 @@ class Output_data_plt_x86_64 : public Output_section_data
do_print_to_mapfile(Mapfile* mapfile) const
{ mapfile->print_output_data(this, _("** PLT")); }
- private:
- // The size of an entry in the PLT.
- static const int plt_entry_size = 16;
-
- // The first entry in the PLT.
- // From the AMD64 ABI: "Unlike Intel386 ABI, this ABI uses the same
- // procedure linkage table for both programs and shared objects."
- static const unsigned char first_plt_entry[plt_entry_size];
-
- // Other entries in the PLT for an executable.
- static const unsigned char plt_entry[plt_entry_size];
-
- // The reserved TLSDESC entry in the PLT for an executable.
- static const unsigned char tlsdesc_plt_entry[plt_entry_size];
-
- // The .eh_frame unwind information for the PLT.
+ // The CIE of the .eh_frame unwind information for the PLT.
static const int plt_eh_frame_cie_size = 16;
- static const int plt_eh_frame_fde_size = 32;
static const unsigned char plt_eh_frame_cie[plt_eh_frame_cie_size];
- static const unsigned char plt_eh_frame_fde[plt_eh_frame_fde_size];
+ private:
// Set the final size.
void
set_final_data_size();
@@ -235,6 +298,84 @@ class Output_data_plt_x86_64 : public Output_section_data
Free_list free_list_;
};
+template<int size>
+class Output_data_plt_x86_64_standard : public Output_data_plt_x86_64<size>
+{
+ public:
+ Output_data_plt_x86_64_standard(Layout* layout,
+ Output_data_got<64, false>* got,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative)
+ : Output_data_plt_x86_64<size>(layout, plt_entry_size,
+ got, got_plt, got_irelative)
+ { }
+
+ Output_data_plt_x86_64_standard(Layout* layout,
+ Output_data_got<64, false>* got,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative,
+ unsigned int plt_count)
+ : Output_data_plt_x86_64<size>(layout, plt_entry_size,
+ got, got_plt, got_irelative,
+ plt_count)
+ { }
+
+ protected:
+ virtual unsigned int
+ do_get_plt_entry_size() const
+ { return plt_entry_size; }
+
+ virtual void
+ do_add_eh_frame(Layout* layout)
+ {
+ layout->add_eh_frame_for_plt(this,
+ this->plt_eh_frame_cie,
+ this->plt_eh_frame_cie_size,
+ plt_eh_frame_fde,
+ plt_eh_frame_fde_size);
+ }
+
+ virtual void
+ do_fill_first_plt_entry(unsigned char* pov,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_addr,
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_addr);
+
+ virtual unsigned int
+ do_fill_plt_entry(unsigned char* pov,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+ unsigned int got_offset,
+ unsigned int plt_offset,
+ unsigned int plt_index);
+
+ virtual void
+ do_fill_tlsdesc_entry(unsigned char* pov,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_base,
+ unsigned int tlsdesc_got_offset,
+ unsigned int plt_offset);
+
+ private:
+ // The size of an entry in the PLT.
+ static const int plt_entry_size = 16;
+
+ // The first entry in the PLT.
+ // From the AMD64 ABI: "Unlike Intel386 ABI, this ABI uses the same
+ // procedure linkage table for both programs and shared objects."
+ static const unsigned char first_plt_entry[plt_entry_size];
+
+ // Other entries in the PLT for an executable.
+ static const unsigned char plt_entry[plt_entry_size];
+
+ // The reserved TLSDESC entry in the PLT for an executable.
+ static const unsigned char tlsdesc_plt_entry[plt_entry_size];
+
+ // The .eh_frame unwind information for the PLT.
+ static const int plt_eh_frame_fde_size = 32;
+ static const unsigned char plt_eh_frame_fde[plt_eh_frame_fde_size];
+};
+
// The x86_64 target class.
// See the ABI at
// http://www.x86-64.org/documentation/abi.pdf
@@ -242,15 +383,16 @@ class Output_data_plt_x86_64 : public Output_section_data
// http://people.redhat.com/drepper/tls.pdf
// http://www.lsd.ic.unicamp.br/~oliva/writeups/TLS/RFC-TLSDESC-x86.txt
-class Target_x86_64 : public Sized_target<64, false>
+template<int size>
+class Target_x86_64 : public Sized_target<size, false>
{
public:
// In the x86_64 ABI (p 68), it says "The AMD64 ABI architectures
// uses only Elf64_Rela relocation entries with explicit addends."
- typedef Output_data_reloc<elfcpp::SHT_RELA, true, 64, false> Reloc_section;
+ typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, false> Reloc_section;
- Target_x86_64()
- : Sized_target<64, false>(&x86_64_info),
+ Target_x86_64(const Target::Target_info* info = &x86_64_info)
+ : Sized_target<size, false>(info),
got_(NULL), plt_(NULL), got_plt_(NULL), got_irelative_(NULL),
got_tlsdesc_(NULL), global_offset_table_(NULL), rela_dyn_(NULL),
rela_irelative_(NULL), copy_relocs_(elfcpp::R_X86_64_COPY),
@@ -265,22 +407,22 @@ class Target_x86_64 : public Sized_target<64, false>
// Scan the relocations to look for symbol adjustments.
void
gc_process_relocs(Symbol_table* symtab,
- Layout* layout,
- Sized_relobj_file<64, false>* object,
- unsigned int data_shndx,
- unsigned int sh_type,
- const unsigned char* prelocs,
- size_t reloc_count,
- Output_section* output_section,
- bool needs_special_offset_handling,
- size_t local_symbol_count,
- const unsigned char* plocal_symbols);
+ Layout* layout,
+ Sized_relobj_file<size, false>* object,
+ unsigned int data_shndx,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ size_t local_symbol_count,
+ const unsigned char* plocal_symbols);
// Scan the relocations to look for symbol adjustments.
void
scan_relocs(Symbol_table* symtab,
Layout* layout,
- Sized_relobj_file<64, false>* object,
+ Sized_relobj_file<size, false>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
@@ -301,14 +443,14 @@ class Target_x86_64 : public Sized_target<64, false>
// Relocate a section.
void
- relocate_section(const Relocate_info<64, false>*,
+ relocate_section(const Relocate_info<size, false>*,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr view_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr view_address,
section_size_type view_size,
const Reloc_symbol_changes*);
@@ -316,7 +458,7 @@ class Target_x86_64 : public Sized_target<64, false>
void
scan_relocatable_relocs(Symbol_table* symtab,
Layout* layout,
- Sized_relobj_file<64, false>* object,
+ Sized_relobj_file<size, false>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
@@ -329,18 +471,19 @@ class Target_x86_64 : public Sized_target<64, false>
// Relocate a section during a relocatable link.
void
- relocate_for_relocatable(const Relocate_info<64, false>*,
- unsigned int sh_type,
- const unsigned char* prelocs,
- size_t reloc_count,
- Output_section* output_section,
- off_t offset_in_output_section,
- const Relocatable_relocs*,
- unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr view_address,
- section_size_type view_size,
- unsigned char* reloc_view,
- section_size_type reloc_view_size);
+ relocate_for_relocatable(
+ const Relocate_info<size, false>*,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ off_t offset_in_output_section,
+ const Relocatable_relocs*,
+ unsigned char* view,
+ typename elfcpp::Elf_types<size>::Elf_Addr view_address,
+ section_size_type view_size,
+ unsigned char* reloc_view,
+ section_size_type reloc_view_size);
// Return a string used to fill a code section with nops.
std::string
@@ -425,7 +568,7 @@ class Target_x86_64 : public Sized_target<64, false>
plt_entry_size() const;
// Create the GOT section for an incremental update.
- Output_data_got<64, false>*
+ Output_data_got_base*
init_got_plt_for_update(Symbol_table* symtab,
Layout* layout,
unsigned int got_count,
@@ -435,7 +578,7 @@ class Target_x86_64 : public Sized_target<64, false>
// necessary dynamic relocations.
void
reserve_local_got_entry(unsigned int got_index,
- Sized_relobj<64, false>* obj,
+ Sized_relobj<size, false>* obj,
unsigned int r_sym,
unsigned int got_type);
@@ -456,23 +599,65 @@ class Target_x86_64 : public Sized_target<64, false>
// Apply an incremental relocation.
void
- apply_relocation(const Relocate_info<64, false>* relinfo,
- elfcpp::Elf_types<64>::Elf_Addr r_offset,
+ apply_relocation(const Relocate_info<size, false>* relinfo,
+ typename elfcpp::Elf_types<size>::Elf_Addr r_offset,
unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Swxword r_addend,
+ typename elfcpp::Elf_types<size>::Elf_Swxword r_addend,
const Symbol* gsym,
unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr address,
+ typename elfcpp::Elf_types<size>::Elf_Addr address,
section_size_type view_size);
// Add a new reloc argument, returning the index in the vector.
size_t
- add_tlsdesc_info(Sized_relobj_file<64, false>* object, unsigned int r_sym)
+ add_tlsdesc_info(Sized_relobj_file<size, false>* object, unsigned int r_sym)
{
this->tlsdesc_reloc_info_.push_back(Tlsdesc_info(object, r_sym));
return this->tlsdesc_reloc_info_.size() - 1;
}
+ Output_data_plt_x86_64<size>*
+ make_data_plt(Layout* layout,
+ Output_data_got<64, false>* got,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative)
+ {
+ return this->do_make_data_plt(layout, got, got_plt, got_irelative);
+ }
+
+ Output_data_plt_x86_64<size>*
+ make_data_plt(Layout* layout,
+ Output_data_got<64, false>* got,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative,
+ unsigned int plt_count)
+ {
+ return this->do_make_data_plt(layout, got, got_plt, got_irelative,
+ plt_count);
+ }
+
+ virtual Output_data_plt_x86_64<size>*
+ do_make_data_plt(Layout* layout,
+ Output_data_got<64, false>* got,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative)
+ {
+ return new Output_data_plt_x86_64_standard<size>(layout, got, got_plt,
+ got_irelative);
+ }
+
+ virtual Output_data_plt_x86_64<size>*
+ do_make_data_plt(Layout* layout,
+ Output_data_got<64, false>* got,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative,
+ unsigned int plt_count)
+ {
+ return new Output_data_plt_x86_64_standard<size>(layout, got, got_plt,
+ got_irelative,
+ plt_count);
+ }
+
private:
// The class which scans relocations.
class Scan
@@ -487,47 +672,48 @@ class Target_x86_64 : public Sized_target<64, false>
inline void
local(Symbol_table* symtab, Layout* layout, Target_x86_64* target,
- Sized_relobj_file<64, false>* object,
+ Sized_relobj_file<size, false>* object,
unsigned int data_shndx,
Output_section* output_section,
- const elfcpp::Rela<64, false>& reloc, unsigned int r_type,
- const elfcpp::Sym<64, false>& lsym);
+ const elfcpp::Rela<size, false>& reloc, unsigned int r_type,
+ const elfcpp::Sym<size, false>& lsym);
inline void
global(Symbol_table* symtab, Layout* layout, Target_x86_64* target,
- Sized_relobj_file<64, false>* object,
+ Sized_relobj_file<size, false>* object,
unsigned int data_shndx,
Output_section* output_section,
- const elfcpp::Rela<64, false>& reloc, unsigned int r_type,
+ const elfcpp::Rela<size, false>& reloc, unsigned int r_type,
Symbol* gsym);
inline bool
local_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout,
Target_x86_64* target,
- Sized_relobj_file<64, false>* object,
- unsigned int data_shndx,
- Output_section* output_section,
- const elfcpp::Rela<64, false>& reloc,
+ Sized_relobj_file<size, false>* object,
+ unsigned int data_shndx,
+ Output_section* output_section,
+ const elfcpp::Rela<size, false>& reloc,
unsigned int r_type,
- const elfcpp::Sym<64, false>& lsym);
+ const elfcpp::Sym<size, false>& lsym);
inline bool
global_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout,
- Target_x86_64* target,
- Sized_relobj_file<64, false>* object,
- unsigned int data_shndx,
- Output_section* output_section,
- const elfcpp::Rela<64, false>& reloc,
+ Target_x86_64* target,
+ Sized_relobj_file<size, false>* object,
+ unsigned int data_shndx,
+ Output_section* output_section,
+ const elfcpp::Rela<size, false>& reloc,
unsigned int r_type,
- Symbol* gsym);
+ Symbol* gsym);
private:
static void
- unsupported_reloc_local(Sized_relobj_file<64, false>*, unsigned int r_type);
+ unsupported_reloc_local(Sized_relobj_file<size, false>*,
+ unsigned int r_type);
static void
- unsupported_reloc_global(Sized_relobj_file<64, false>*, unsigned int r_type,
- Symbol*);
+ unsupported_reloc_global(Sized_relobj_file<size, false>*,
+ unsigned int r_type, Symbol*);
void
check_non_pic(Relobj*, unsigned int r_type, Symbol*);
@@ -536,7 +722,7 @@ class Target_x86_64 : public Sized_target<64, false>
possible_function_pointer_reloc(unsigned int r_type);
bool
- reloc_needs_plt_for_ifunc(Sized_relobj_file<64, false>*,
+ reloc_needs_plt_for_ifunc(Sized_relobj_file<size, false>*,
unsigned int r_type);
// Whether we have issued an error about a non-PIC compilation.
@@ -563,76 +749,77 @@ class Target_x86_64 : public Sized_target<64, false>
// Do a relocation. Return false if the caller should not issue
// any warnings about this relocation.
inline bool
- relocate(const Relocate_info<64, false>*, Target_x86_64*, Output_section*,
- size_t relnum, const elfcpp::Rela<64, false>&,
- unsigned int r_type, const Sized_symbol<64>*,
- const Symbol_value<64>*,
- unsigned char*, elfcpp::Elf_types<64>::Elf_Addr,
+ relocate(const Relocate_info<size, false>*, Target_x86_64*,
+ Output_section*,
+ size_t relnum, const elfcpp::Rela<size, false>&,
+ unsigned int r_type, const Sized_symbol<size>*,
+ const Symbol_value<size>*,
+ unsigned char*, typename elfcpp::Elf_types<size>::Elf_Addr,
section_size_type);
private:
// Do a TLS relocation.
inline void
- relocate_tls(const Relocate_info<64, false>*, Target_x86_64*,
- size_t relnum, const elfcpp::Rela<64, false>&,
- unsigned int r_type, const Sized_symbol<64>*,
- const Symbol_value<64>*,
- unsigned char*, elfcpp::Elf_types<64>::Elf_Addr,
+ relocate_tls(const Relocate_info<size, false>*, Target_x86_64*,
+ size_t relnum, const elfcpp::Rela<size, false>&,
+ unsigned int r_type, const Sized_symbol<size>*,
+ const Symbol_value<size>*,
+ unsigned char*, typename elfcpp::Elf_types<size>::Elf_Addr,
section_size_type);
// Do a TLS General-Dynamic to Initial-Exec transition.
inline void
- tls_gd_to_ie(const Relocate_info<64, false>*, size_t relnum,
+ tls_gd_to_ie(const Relocate_info<size, false>*, size_t relnum,
Output_segment* tls_segment,
- const elfcpp::Rela<64, false>&, unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Addr value,
+ const elfcpp::Rela<size, false>&, unsigned int r_type,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr,
+ typename elfcpp::Elf_types<size>::Elf_Addr,
section_size_type view_size);
// Do a TLS General-Dynamic to Local-Exec transition.
inline void
- tls_gd_to_le(const Relocate_info<64, false>*, size_t relnum,
+ tls_gd_to_le(const Relocate_info<size, false>*, size_t relnum,
Output_segment* tls_segment,
- const elfcpp::Rela<64, false>&, unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Addr value,
+ const elfcpp::Rela<size, false>&, unsigned int r_type,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned char* view,
section_size_type view_size);
// Do a TLSDESC-style General-Dynamic to Initial-Exec transition.
inline void
- tls_desc_gd_to_ie(const Relocate_info<64, false>*, size_t relnum,
+ tls_desc_gd_to_ie(const Relocate_info<size, false>*, size_t relnum,
Output_segment* tls_segment,
- const elfcpp::Rela<64, false>&, unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Addr value,
+ const elfcpp::Rela<size, false>&, unsigned int r_type,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr,
+ typename elfcpp::Elf_types<size>::Elf_Addr,
section_size_type view_size);
// Do a TLSDESC-style General-Dynamic to Local-Exec transition.
inline void
- tls_desc_gd_to_le(const Relocate_info<64, false>*, size_t relnum,
+ tls_desc_gd_to_le(const Relocate_info<size, false>*, size_t relnum,
Output_segment* tls_segment,
- const elfcpp::Rela<64, false>&, unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Addr value,
+ const elfcpp::Rela<size, false>&, unsigned int r_type,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned char* view,
section_size_type view_size);
// Do a TLS Local-Dynamic to Local-Exec transition.
inline void
- tls_ld_to_le(const Relocate_info<64, false>*, size_t relnum,
+ tls_ld_to_le(const Relocate_info<size, false>*, size_t relnum,
Output_segment* tls_segment,
- const elfcpp::Rela<64, false>&, unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Addr value,
+ const elfcpp::Rela<size, false>&, unsigned int r_type,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned char* view,
section_size_type view_size);
// Do a TLS Initial-Exec to Local-Exec transition.
static inline void
- tls_ie_to_le(const Relocate_info<64, false>*, size_t relnum,
+ tls_ie_to_le(const Relocate_info<size, false>*, size_t relnum,
Output_segment* tls_segment,
- const elfcpp::Rela<64, false>&, unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Addr value,
+ const elfcpp::Rela<size, false>&, unsigned int r_type,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned char* view,
section_size_type view_size);
@@ -686,7 +873,7 @@ class Target_x86_64 : public Sized_target<64, false>
// Create a PLT entry for a local STT_GNU_IFUNC symbol.
void
make_local_ifunc_plt_entry(Symbol_table*, Layout*,
- Sized_relobj_file<64, false>* relobj,
+ Sized_relobj_file<size, false>* relobj,
unsigned int local_sym_index);
// Define the _TLS_MODULE_BASE_ symbol in the TLS segment.
@@ -700,10 +887,10 @@ class Target_x86_64 : public Sized_target<64, false>
// Create a GOT entry for the TLS module index.
unsigned int
got_mod_index_entry(Symbol_table* symtab, Layout* layout,
- Sized_relobj_file<64, false>* object);
+ Sized_relobj_file<size, false>* object);
// Get the PLT section.
- Output_data_plt_x86_64*
+ Output_data_plt_x86_64<size>*
plt_section() const
{
gold_assert(this->plt_ != NULL);
@@ -725,12 +912,12 @@ class Target_x86_64 : public Sized_target<64, false>
// Add a potential copy relocation.
void
copy_reloc(Symbol_table* symtab, Layout* layout,
- Sized_relobj_file<64, false>* object,
+ Sized_relobj_file<size, false>* object,
unsigned int shndx, Output_section* output_section,
- Symbol* sym, const elfcpp::Rela<64, false>& reloc)
+ Symbol* sym, const elfcpp::Rela<size, false>& reloc)
{
this->copy_relocs_.copy_reloc(symtab, layout,
- symtab->get_sized_symbol<64>(sym),
+ symtab->get_sized_symbol<size>(sym),
object, shndx, output_section,
reloc, this->rela_dyn_section(layout));
}
@@ -756,12 +943,12 @@ class Target_x86_64 : public Sized_target<64, false>
// R_X86_64_TLSDESC against a local symbol.
struct Tlsdesc_info
{
- Tlsdesc_info(Sized_relobj_file<64, false>* a_object, unsigned int a_r_sym)
+ Tlsdesc_info(Sized_relobj_file<size, false>* a_object, unsigned int a_r_sym)
: object(a_object), r_sym(a_r_sym)
{ }
// The object in which the local symbol is defined.
- Sized_relobj_file<64, false>* object;
+ Sized_relobj_file<size, false>* object;
// The local symbol index in the object.
unsigned int r_sym;
};
@@ -769,7 +956,7 @@ class Target_x86_64 : public Sized_target<64, false>
// The GOT section.
Output_data_got<64, false>* got_;
// The PLT section.
- Output_data_plt_x86_64* plt_;
+ Output_data_plt_x86_64<size>* plt_;
// The GOT PLT section.
Output_data_space* got_plt_;
// The GOT section for IRELATIVE relocations.
@@ -783,7 +970,7 @@ class Target_x86_64 : public Sized_target<64, false>
// The section to use for IRELATIVE relocs.
Reloc_section* rela_irelative_;
// Relocs saved to avoid a COPY reloc.
- Copy_relocs<elfcpp::SHT_RELA, 64, false> copy_relocs_;
+ Copy_relocs<elfcpp::SHT_RELA, size, false> copy_relocs_;
// Space for variables copied with a COPY reloc.
Output_data_space* dynbss_;
// Offset of the GOT entry for the TLS module index.
@@ -796,7 +983,8 @@ class Target_x86_64 : public Sized_target<64, false>
bool tls_base_symbol_defined_;
};
-const Target::Target_info Target_x86_64::x86_64_info =
+template<>
+const Target::Target_info Target_x86_64<64>::x86_64_info =
{
64, // size
false, // is_big_endian
@@ -811,6 +999,34 @@ const Target::Target_info Target_x86_64::x86_64_info =
0x400000, // default_text_segment_address
0x1000, // abi_pagesize (overridable by -z max-page-size)
0x1000, // common_pagesize (overridable by -z common-page-size)
+ false, // isolate_execinstr
+ 0, // rosegment_gap
+ elfcpp::SHN_UNDEF, // small_common_shndx
+ elfcpp::SHN_X86_64_LCOMMON, // large_common_shndx
+ 0, // small_common_section_flags
+ elfcpp::SHF_X86_64_LARGE, // large_common_section_flags
+ NULL, // attributes_section
+ NULL // attributes_vendor
+};
+
+template<>
+const Target::Target_info Target_x86_64<32>::x86_64_info =
+{
+ 32, // size
+ false, // is_big_endian
+ elfcpp::EM_X86_64, // machine_code
+ false, // has_make_symbol
+ false, // has_resolve
+ true, // has_code_fill
+ true, // is_default_stack_executable
+ true, // can_icf_inline_merge_sections
+ '\0', // wrap_char
+ "/libx32/ldx32.so.1", // program interpreter
+ 0x400000, // default_text_segment_address
+ 0x1000, // abi_pagesize (overridable by -z max-page-size)
+ 0x1000, // common_pagesize (overridable by -z common-page-size)
+ false, // isolate_execinstr
+ 0, // rosegment_gap
elfcpp::SHN_UNDEF, // small_common_shndx
elfcpp::SHN_X86_64_LCOMMON, // large_common_shndx
0, // small_common_section_flags
@@ -822,8 +1038,9 @@ const Target::Target_info Target_x86_64::x86_64_info =
// This is called when a new output section is created. This is where
// we handle the SHF_X86_64_LARGE.
+template<int size>
void
-Target_x86_64::do_new_output_section(Output_section* os) const
+Target_x86_64<size>::do_new_output_section(Output_section* os) const
{
if ((os->flags() & elfcpp::SHF_X86_64_LARGE) != 0)
os->set_is_large_section();
@@ -831,8 +1048,9 @@ Target_x86_64::do_new_output_section(Output_section* os) const
// Get the GOT section, creating it if necessary.
+template<int size>
Output_data_got<64, false>*
-Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
+Target_x86_64<size>::got_section(Symbol_table* symtab, Layout* layout)
{
if (this->got_ == NULL)
{
@@ -906,8 +1124,9 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
// Get the dynamic reloc section, creating it if necessary.
-Target_x86_64::Reloc_section*
-Target_x86_64::rela_dyn_section(Layout* layout)
+template<int size>
+typename Target_x86_64<size>::Reloc_section*
+Target_x86_64<size>::rela_dyn_section(Layout* layout)
{
if (this->rela_dyn_ == NULL)
{
@@ -926,8 +1145,9 @@ Target_x86_64::rela_dyn_section(Layout* layout)
// that they can refer to global variables initialized by those
// relocs.
-Target_x86_64::Reloc_section*
-Target_x86_64::rela_irelative_section(Layout* layout)
+template<int size>
+typename Target_x86_64<size>::Reloc_section*
+Target_x86_64<size>::rela_irelative_section(Layout* layout)
{
if (this->rela_irelative_ == NULL)
{
@@ -945,31 +1165,29 @@ Target_x86_64::rela_irelative_section(Layout* layout)
// Initialize the PLT section.
+template<int size>
void
-Output_data_plt_x86_64::init(Layout* layout)
+Output_data_plt_x86_64<size>::init(Layout* layout)
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
elfcpp::SHF_ALLOC, this->rel_,
ORDER_DYNAMIC_PLT_RELOCS, false);
-
- // Add unwind information if requested.
- if (parameters->options().ld_generated_unwind_info())
- layout->add_eh_frame_for_plt(this, plt_eh_frame_cie, plt_eh_frame_cie_size,
- plt_eh_frame_fde, plt_eh_frame_fde_size);
}
+template<int size>
void
-Output_data_plt_x86_64::do_adjust_output_section(Output_section* os)
+Output_data_plt_x86_64<size>::do_adjust_output_section(Output_section* os)
{
- os->set_entsize(plt_entry_size);
+ os->set_entsize(this->get_plt_entry_size());
}
// Add an entry to the PLT.
+template<int size>
void
-Output_data_plt_x86_64::add_entry(Symbol_table* symtab, Layout* layout,
- Symbol* gsym)
+Output_data_plt_x86_64<size>::add_entry(Symbol_table* symtab, Layout* layout,
+ Symbol* gsym)
{
gold_assert(!gsym->has_plt_offset());
@@ -1002,7 +1220,7 @@ Output_data_plt_x86_64::add_entry(Symbol_table* symtab, Layout* layout,
// Note that when setting the PLT offset for a non-IRELATIVE
// entry we skip the initial reserved PLT entry.
plt_index = *pcount + offset;
- plt_offset = plt_index * plt_entry_size;
+ plt_offset = plt_index * this->get_plt_entry_size();
++*pcount;
@@ -1019,7 +1237,8 @@ Output_data_plt_x86_64::add_entry(Symbol_table* symtab, Layout* layout,
// FIXME: This is probably not correct for IRELATIVE relocs.
// For incremental updates, find an available slot.
- plt_offset = this->free_list_.allocate(plt_entry_size, plt_entry_size, 0);
+ plt_offset = this->free_list_.allocate(this->get_plt_entry_size(),
+ this->get_plt_entry_size(), 0);
if (plt_offset == -1)
gold_fallback(_("out of patch space (PLT);"
" relink with --incremental-full"));
@@ -1027,7 +1246,7 @@ Output_data_plt_x86_64::add_entry(Symbol_table* symtab, Layout* layout,
// The GOT and PLT entries have a 1-1 correspondance, so the GOT offset
// can be calculated from the PLT index, adjusting for the three
// reserved entries at the beginning of the GOT.
- plt_index = plt_offset / plt_entry_size - 1;
+ plt_index = plt_offset / this->get_plt_entry_size() - 1;
got_offset = (plt_index - offset + reserved) * 8;
}
@@ -1044,14 +1263,15 @@ Output_data_plt_x86_64::add_entry(Symbol_table* symtab, Layout* layout,
// Add an entry to the PLT for a local STT_GNU_IFUNC symbol. Return
// the PLT offset.
+template<int size>
unsigned int
-Output_data_plt_x86_64::add_local_ifunc_entry(
+Output_data_plt_x86_64<size>::add_local_ifunc_entry(
Symbol_table* symtab,
Layout* layout,
- Sized_relobj_file<64, false>* relobj,
+ Sized_relobj_file<size, false>* relobj,
unsigned int local_sym_index)
{
- unsigned int plt_offset = this->irelative_count_ * plt_entry_size;
+ unsigned int plt_offset = this->irelative_count_ * this->get_plt_entry_size();
++this->irelative_count_;
section_offset_type got_offset = this->got_irelative_->current_data_size();
@@ -1071,9 +1291,12 @@ Output_data_plt_x86_64::add_local_ifunc_entry(
// Add the relocation for a PLT entry.
+template<int size>
void
-Output_data_plt_x86_64::add_relocation(Symbol_table* symtab, Layout* layout,
- Symbol* gsym, unsigned int got_offset)
+Output_data_plt_x86_64<size>::add_relocation(Symbol_table* symtab,
+ Layout* layout,
+ Symbol* gsym,
+ unsigned int got_offset)
{
if (gsym->type() == elfcpp::STT_GNU_IFUNC
&& gsym->can_use_relative_reloc(false))
@@ -1093,8 +1316,9 @@ Output_data_plt_x86_64::add_relocation(Symbol_table* symtab, Layout* layout,
// Return where the TLSDESC relocations should go, creating it if
// necessary. These follow the JUMP_SLOT relocations.
-Output_data_plt_x86_64::Reloc_section*
-Output_data_plt_x86_64::rela_tlsdesc(Layout* layout)
+template<int size>
+typename Output_data_plt_x86_64<size>::Reloc_section*
+Output_data_plt_x86_64<size>::rela_tlsdesc(Layout* layout)
{
if (this->tlsdesc_rel_ == NULL)
{
@@ -1111,8 +1335,10 @@ Output_data_plt_x86_64::rela_tlsdesc(Layout* layout)
// Return where the IRELATIVE relocations should go in the PLT. These
// follow the JUMP_SLOT and the TLSDESC relocations.
-Output_data_plt_x86_64::Reloc_section*
-Output_data_plt_x86_64::rela_irelative(Symbol_table* symtab, Layout* layout)
+template<int size>
+typename Output_data_plt_x86_64<size>::Reloc_section*
+Output_data_plt_x86_64<size>::rela_irelative(Symbol_table* symtab,
+ Layout* layout)
{
if (this->irelative_rel_ == NULL)
{
@@ -1150,38 +1376,43 @@ Output_data_plt_x86_64::rela_irelative(Symbol_table* symtab, Layout* layout)
// Return the PLT address to use for a global symbol.
+template<int size>
uint64_t
-Output_data_plt_x86_64::address_for_global(const Symbol* gsym)
+Output_data_plt_x86_64<size>::address_for_global(const Symbol* gsym)
{
uint64_t offset = 0;
if (gsym->type() == elfcpp::STT_GNU_IFUNC
&& gsym->can_use_relative_reloc(false))
- offset = (this->count_ + 1) * plt_entry_size;
+ offset = (this->count_ + 1) * this->get_plt_entry_size();
return this->address() + offset;
}
// Return the PLT address to use for a local symbol. These are always
// IRELATIVE relocs.
+template<int size>
uint64_t
-Output_data_plt_x86_64::address_for_local(const Relobj*, unsigned int)
+Output_data_plt_x86_64<size>::address_for_local(const Relobj*, unsigned int)
{
- return this->address() + (this->count_ + 1) * plt_entry_size;
+ return this->address() + (this->count_ + 1) * this->get_plt_entry_size();
}
// Set the final size.
+template<int size>
void
-Output_data_plt_x86_64::set_final_data_size()
+Output_data_plt_x86_64<size>::set_final_data_size()
{
unsigned int count = this->count_ + this->irelative_count_;
if (this->has_tlsdesc_entry())
++count;
- this->set_data_size((count + 1) * plt_entry_size);
+ this->set_data_size((count + 1) * this->get_plt_entry_size());
}
// The first entry in the PLT for an executable.
-const unsigned char Output_data_plt_x86_64::first_plt_entry[plt_entry_size] =
+template<int size>
+const unsigned char
+Output_data_plt_x86_64_standard<size>::first_plt_entry[plt_entry_size] =
{
// From AMD64 ABI Draft 0.98, page 76
0xff, 0x35, // pushq contents of memory address
@@ -1191,9 +1422,28 @@ const unsigned char Output_data_plt_x86_64::first_plt_entry[plt_entry_size] =
0x90, 0x90, 0x90, 0x90 // noop (x4)
};
+template<int size>
+void
+Output_data_plt_x86_64_standard<size>::do_fill_first_plt_entry(
+ unsigned char* pov,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_address)
+{
+ memcpy(pov, first_plt_entry, plt_entry_size);
+ // We do a jmp relative to the PC at the end of this instruction.
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
+ (got_address + 8
+ - (plt_address + 6)));
+ elfcpp::Swap<32, false>::writeval(pov + 8,
+ (got_address + 16
+ - (plt_address + 12)));
+}
+
// Subsequent entries in the PLT for an executable.
-const unsigned char Output_data_plt_x86_64::plt_entry[plt_entry_size] =
+template<int size>
+const unsigned char
+Output_data_plt_x86_64_standard<size>::plt_entry[plt_entry_size] =
{
// From AMD64 ABI Draft 0.98, page 76
0xff, 0x25, // jmpq indirect
@@ -1204,9 +1454,34 @@ const unsigned char Output_data_plt_x86_64::plt_entry[plt_entry_size] =
0, 0, 0, 0 // replaced with offset to start of .plt
};
+template<int size>
+unsigned int
+Output_data_plt_x86_64_standard<size>::do_fill_plt_entry(
+ unsigned char* pov,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+ unsigned int got_offset,
+ unsigned int plt_offset,
+ unsigned int plt_index)
+{
+ memcpy(pov, plt_entry, plt_entry_size);
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
+ (got_address + got_offset
+ - (plt_address + plt_offset
+ + 6)));
+
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 7, plt_index);
+ elfcpp::Swap<32, false>::writeval(pov + 12,
+ - (plt_offset + plt_entry_size));
+
+ return 6;
+}
+
// The reserved TLSDESC entry in the PLT for an executable.
-const unsigned char Output_data_plt_x86_64::tlsdesc_plt_entry[plt_entry_size] =
+template<int size>
+const unsigned char
+Output_data_plt_x86_64_standard<size>::tlsdesc_plt_entry[plt_entry_size] =
{
// From Alexandre Oliva, "Thread-Local Storage Descriptors for IA32
// and AMD64/EM64T", Version 0.9.4 (2005-10-10).
@@ -1218,10 +1493,33 @@ const unsigned char Output_data_plt_x86_64::tlsdesc_plt_entry[plt_entry_size] =
0x40, 0
};
+template<int size>
+void
+Output_data_plt_x86_64_standard<size>::do_fill_tlsdesc_entry(
+ unsigned char* pov,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_base,
+ unsigned int tlsdesc_got_offset,
+ unsigned int plt_offset)
+{
+ memcpy(pov, tlsdesc_plt_entry, plt_entry_size);
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
+ (got_address + 8
+ - (plt_address + plt_offset
+ + 6)));
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 8,
+ (got_base
+ + tlsdesc_got_offset
+ - (plt_address + plt_offset
+ + 12)));
+}
+
// The .eh_frame unwind information for the PLT.
-const unsigned char
-Output_data_plt_x86_64::plt_eh_frame_cie[plt_eh_frame_cie_size] =
+template<int size>
+const unsigned char
+Output_data_plt_x86_64<size>::plt_eh_frame_cie[plt_eh_frame_cie_size] =
{
1, // CIE version.
'z', // Augmentation: augmentation size included.
@@ -1239,8 +1537,9 @@ Output_data_plt_x86_64::plt_eh_frame_cie[plt_eh_frame_cie_size] =
elfcpp::DW_CFA_nop
};
+template<int size>
const unsigned char
-Output_data_plt_x86_64::plt_eh_frame_fde[plt_eh_frame_fde_size] =
+Output_data_plt_x86_64_standard<size>::plt_eh_frame_fde[plt_eh_frame_fde_size] =
{
0, 0, 0, 0, // Replaced with offset to .plt.
0, 0, 0, 0, // Replaced with size of .plt.
@@ -1269,8 +1568,9 @@ Output_data_plt_x86_64::plt_eh_frame_fde[plt_eh_frame_fde_size] =
// Write out the PLT. This uses the hand-coded instructions above,
// and adjusts them as needed. This is specified by the AMD64 ABI.
+template<int size>
void
-Output_data_plt_x86_64::do_write(Output_file* of)
+Output_data_plt_x86_64<size>::do_write(Output_file* of)
{
const off_t offset = this->offset();
const section_size_type oview_size =
@@ -1290,23 +1590,17 @@ Output_data_plt_x86_64::do_write(Output_file* of)
unsigned char* pov = oview;
// The base address of the .plt section.
- elfcpp::Elf_types<64>::Elf_Addr plt_address = this->address();
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_address = this->address();
// The base address of the .got section.
- elfcpp::Elf_types<64>::Elf_Addr got_base = this->got_->address();
+ typename elfcpp::Elf_types<size>::Elf_Addr got_base = this->got_->address();
// The base address of the PLT portion of the .got section,
// which is where the GOT pointer will point, and where the
// three reserved GOT entries are located.
- elfcpp::Elf_types<64>::Elf_Addr got_address = this->got_plt_->address();
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address
+ = this->got_plt_->address();
- memcpy(pov, first_plt_entry, plt_entry_size);
- // We do a jmp relative to the PC at the end of this instruction.
- elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
- (got_address + 8
- - (plt_address + 6)));
- elfcpp::Swap<32, false>::writeval(pov + 8,
- (got_address + 16
- - (plt_address + 12)));
- pov += plt_entry_size;
+ this->fill_first_plt_entry(pov, got_address, plt_address);
+ pov += this->get_plt_entry_size();
unsigned char* got_pov = got_view;
@@ -1321,47 +1615,35 @@ Output_data_plt_x86_64::do_write(Output_file* of)
memset(got_pov, 0, 16);
got_pov += 16;
- unsigned int plt_offset = plt_entry_size;
+ unsigned int plt_offset = this->get_plt_entry_size();
unsigned int got_offset = 24;
const unsigned int count = this->count_ + this->irelative_count_;
for (unsigned int plt_index = 0;
plt_index < count;
++plt_index,
- pov += plt_entry_size,
+ pov += this->get_plt_entry_size(),
got_pov += 8,
- plt_offset += plt_entry_size,
+ plt_offset += this->get_plt_entry_size(),
got_offset += 8)
{
// Set and adjust the PLT entry itself.
- memcpy(pov, plt_entry, plt_entry_size);
- elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
- (got_address + got_offset
- - (plt_address + plt_offset
- + 6)));
-
- elfcpp::Swap_unaligned<32, false>::writeval(pov + 7, plt_index);
- elfcpp::Swap<32, false>::writeval(pov + 12,
- - (plt_offset + plt_entry_size));
+ unsigned int lazy_offset = this->fill_plt_entry(pov,
+ got_address, plt_address,
+ got_offset, plt_offset,
+ plt_index);
// Set the entry in the GOT.
- elfcpp::Swap<64, false>::writeval(got_pov, plt_address + plt_offset + 6);
+ elfcpp::Swap<64, false>::writeval(got_pov,
+ plt_address + plt_offset + lazy_offset);
}
if (this->has_tlsdesc_entry())
{
// Set and adjust the reserved TLSDESC PLT entry.
unsigned int tlsdesc_got_offset = this->get_tlsdesc_got_offset();
- memcpy(pov, tlsdesc_plt_entry, plt_entry_size);
- elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
- (got_address + 8
- - (plt_address + plt_offset
- + 6)));
- elfcpp::Swap_unaligned<32, false>::writeval(pov + 8,
- (got_base
- + tlsdesc_got_offset
- - (plt_address + plt_offset
- + 12)));
- pov += plt_entry_size;
+ this->fill_tlsdesc_entry(pov, got_address, plt_address, got_base,
+ tlsdesc_got_offset, plt_offset);
+ pov += this->get_plt_entry_size();
}
gold_assert(static_cast<section_size_type>(pov - oview) == oview_size);
@@ -1373,17 +1655,22 @@ Output_data_plt_x86_64::do_write(Output_file* of)
// Create the PLT section.
+template<int size>
void
-Target_x86_64::make_plt_section(Symbol_table* symtab, Layout* layout)
+Target_x86_64<size>::make_plt_section(Symbol_table* symtab, Layout* layout)
{
if (this->plt_ == NULL)
{
// Create the GOT sections first.
this->got_section(symtab, layout);
- this->plt_ = new Output_data_plt_x86_64(layout, this->got_,
- this->got_plt_,
- this->got_irelative_);
+ this->plt_ = this->make_data_plt(layout, this->got_, this->got_plt_,
+ this->got_irelative_);
+
+ // Add unwind information if requested.
+ if (parameters->options().ld_generated_unwind_info())
+ this->plt_->add_eh_frame(layout);
+
layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR),
@@ -1397,17 +1684,19 @@ Target_x86_64::make_plt_section(Symbol_table* symtab, Layout* layout)
// Return the section for TLSDESC relocations.
-Target_x86_64::Reloc_section*
-Target_x86_64::rela_tlsdesc_section(Layout* layout) const
+template<int size>
+typename Target_x86_64<size>::Reloc_section*
+Target_x86_64<size>::rela_tlsdesc_section(Layout* layout) const
{
return this->plt_section()->rela_tlsdesc(layout);
}
// Create a PLT entry for a global symbol.
+template<int size>
void
-Target_x86_64::make_plt_entry(Symbol_table* symtab, Layout* layout,
- Symbol* gsym)
+Target_x86_64<size>::make_plt_entry(Symbol_table* symtab, Layout* layout,
+ Symbol* gsym)
{
if (gsym->has_plt_offset())
return;
@@ -1420,10 +1709,12 @@ Target_x86_64::make_plt_entry(Symbol_table* symtab, Layout* layout,
// Make a PLT entry for a local STT_GNU_IFUNC symbol.
+template<int size>
void
-Target_x86_64::make_local_ifunc_plt_entry(Symbol_table* symtab, Layout* layout,
- Sized_relobj_file<64, false>* relobj,
- unsigned int local_sym_index)
+Target_x86_64<size>::make_local_ifunc_plt_entry(
+ Symbol_table* symtab, Layout* layout,
+ Sized_relobj_file<size, false>* relobj,
+ unsigned int local_sym_index)
{
if (relobj->local_has_plt_offset(local_sym_index))
return;
@@ -1437,8 +1728,9 @@ Target_x86_64::make_local_ifunc_plt_entry(Symbol_table* symtab, Layout* layout,
// Return the number of entries in the PLT.
+template<int size>
unsigned int
-Target_x86_64::plt_entry_count() const
+Target_x86_64<size>::plt_entry_count() const
{
if (this->plt_ == NULL)
return 0;
@@ -1447,24 +1739,27 @@ Target_x86_64::plt_entry_count() const
// Return the offset of the first non-reserved PLT entry.
+template<int size>
unsigned int
-Target_x86_64::first_plt_entry_offset() const
+Target_x86_64<size>::first_plt_entry_offset() const
{
- return Output_data_plt_x86_64::first_plt_entry_offset();
+ return this->plt_->first_plt_entry_offset();
}
// Return the size of each PLT entry.
+template<int size>
unsigned int
-Target_x86_64::plt_entry_size() const
+Target_x86_64<size>::plt_entry_size() const
{
- return Output_data_plt_x86_64::get_plt_entry_size();
+ return this->plt_->get_plt_entry_size();
}
// Create the GOT and PLT sections for an incremental update.
-Output_data_got<64, false>*
-Target_x86_64::init_got_plt_for_update(Symbol_table* symtab,
+template<int size>
+Output_data_got_base*
+Target_x86_64<size>::init_got_plt_for_update(Symbol_table* symtab,
Layout* layout,
unsigned int got_count,
unsigned int plt_count)
@@ -1514,8 +1809,15 @@ Target_x86_64::init_got_plt_for_update(Symbol_table* symtab,
ORDER_NON_RELRO_FIRST, false);
// Create the PLT section.
- this->plt_ = new Output_data_plt_x86_64(layout, this->got_, this->got_plt_,
- this->got_irelative_, plt_count);
+ this->plt_ = this->make_data_plt(layout, this->got_,
+ this->got_plt_,
+ this->got_irelative_,
+ plt_count);
+
+ // Add unwind information if requested.
+ if (parameters->options().ld_generated_unwind_info())
+ this->plt_->add_eh_frame(layout);
+
layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR,
this->plt_, ORDER_PLT, false);
@@ -1533,10 +1835,11 @@ Target_x86_64::init_got_plt_for_update(Symbol_table* symtab,
// Reserve a GOT entry for a local symbol, and regenerate any
// necessary dynamic relocations.
+template<int size>
void
-Target_x86_64::reserve_local_got_entry(
+Target_x86_64<size>::reserve_local_got_entry(
unsigned int got_index,
- Sized_relobj<64, false>* obj,
+ Sized_relobj<size, false>* obj,
unsigned int r_sym,
unsigned int got_type)
{
@@ -1549,7 +1852,7 @@ Target_x86_64::reserve_local_got_entry(
case GOT_TYPE_STANDARD:
if (parameters->options().output_is_position_independent())
rela_dyn->add_local_relative(obj, r_sym, elfcpp::R_X86_64_RELATIVE,
- this->got_, got_offset, 0);
+ this->got_, got_offset, 0, false);
break;
case GOT_TYPE_TLS_OFFSET:
rela_dyn->add_local(obj, r_sym, elfcpp::R_X86_64_TPOFF64,
@@ -1574,9 +1877,11 @@ Target_x86_64::reserve_local_got_entry(
// Reserve a GOT entry for a global symbol, and regenerate any
// necessary dynamic relocations.
+template<int size>
void
-Target_x86_64::reserve_global_got_entry(unsigned int got_index, Symbol* gsym,
- unsigned int got_type)
+Target_x86_64<size>::reserve_global_got_entry(unsigned int got_index,
+ Symbol* gsym,
+ unsigned int got_type)
{
unsigned int got_offset = got_index * 8;
Reloc_section* rela_dyn = this->rela_dyn_section(NULL);
@@ -1595,24 +1900,24 @@ Target_x86_64::reserve_global_got_entry(unsigned int got_index, Symbol* gsym,
this->got_, got_offset, 0);
else
rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_RELATIVE,
- this->got_, got_offset, 0);
+ this->got_, got_offset, 0, false);
}
break;
case GOT_TYPE_TLS_OFFSET:
rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_TPOFF64,
- this->got_, got_offset, 0);
+ this->got_, got_offset, 0, false);
break;
case GOT_TYPE_TLS_PAIR:
this->got_->reserve_slot(got_index + 1);
rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_DTPMOD64,
- this->got_, got_offset, 0);
+ this->got_, got_offset, 0, false);
rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_DTPOFF64,
- this->got_, got_offset + 8, 0);
+ this->got_, got_offset + 8, 0, false);
break;
case GOT_TYPE_TLS_DESC:
this->got_->reserve_slot(got_index + 1);
rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_TLSDESC,
- this->got_, got_offset, 0);
+ this->got_, got_offset, 0, false);
break;
default:
gold_unreachable();
@@ -1621,11 +1926,12 @@ Target_x86_64::reserve_global_got_entry(unsigned int got_index, Symbol* gsym,
// Register an existing PLT entry for a global symbol.
+template<int size>
void
-Target_x86_64::register_global_plt_entry(Symbol_table* symtab,
- Layout* layout,
- unsigned int plt_index,
- Symbol* gsym)
+Target_x86_64<size>::register_global_plt_entry(Symbol_table* symtab,
+ Layout* layout,
+ unsigned int plt_index,
+ Symbol* gsym)
{
gold_assert(this->plt_ != NULL);
gold_assert(!gsym->has_plt_offset());
@@ -1640,12 +1946,13 @@ Target_x86_64::register_global_plt_entry(Symbol_table* symtab,
// Force a COPY relocation for a given symbol.
+template<int size>
void
-Target_x86_64::emit_copy_reloc(
+Target_x86_64<size>::emit_copy_reloc(
Symbol_table* symtab, Symbol* sym, Output_section* os, off_t offset)
{
this->copy_relocs_.emit_copy_reloc(symtab,
- symtab->get_sized_symbol<64>(sym),
+ symtab->get_sized_symbol<size>(sym),
os,
offset,
this->rela_dyn_section(NULL));
@@ -1653,8 +1960,10 @@ Target_x86_64::emit_copy_reloc(
// Define the _TLS_MODULE_BASE_ symbol in the TLS segment.
+template<int size>
void
-Target_x86_64::define_tls_base_symbol(Symbol_table* symtab, Layout* layout)
+Target_x86_64<size>::define_tls_base_symbol(Symbol_table* symtab,
+ Layout* layout)
{
if (this->tls_base_symbol_defined_)
return;
@@ -1679,9 +1988,10 @@ Target_x86_64::define_tls_base_symbol(Symbol_table* symtab, Layout* layout)
// Create the reserved PLT and GOT entries for the TLS descriptor resolver.
+template<int size>
void
-Target_x86_64::reserve_tlsdesc_entries(Symbol_table* symtab,
- Layout* layout)
+Target_x86_64<size>::reserve_tlsdesc_entries(Symbol_table* symtab,
+ Layout* layout)
{
if (this->plt_ == NULL)
this->make_plt_section(symtab, layout);
@@ -1699,9 +2009,10 @@ Target_x86_64::reserve_tlsdesc_entries(Symbol_table* symtab,
// Create a GOT entry for the TLS module index.
+template<int size>
unsigned int
-Target_x86_64::got_mod_index_entry(Symbol_table* symtab, Layout* layout,
- Sized_relobj_file<64, false>* object)
+Target_x86_64<size>::got_mod_index_entry(Symbol_table* symtab, Layout* layout,
+ Sized_relobj_file<size, false>* object)
{
if (this->got_mod_index_offset_ == -1U)
{
@@ -1710,7 +2021,7 @@ Target_x86_64::got_mod_index_entry(Symbol_table* symtab, Layout* layout,
Output_data_got<64, false>* got = this->got_section(symtab, layout);
unsigned int got_offset = got->add_constant(0);
rela_dyn->add_local(object, 0, elfcpp::R_X86_64_DTPMOD64, got,
- got_offset, 0);
+ got_offset, 0);
got->add_constant(0);
this->got_mod_index_offset_ = got_offset;
}
@@ -1721,8 +2032,9 @@ Target_x86_64::got_mod_index_entry(Symbol_table* symtab, Layout* layout,
// symbol. IS_FINAL is true if the final address of this symbol is
// known at link time.
+template<int size>
tls::Tls_optimization
-Target_x86_64::optimize_tls_reloc(bool is_final, int r_type)
+Target_x86_64<size>::optimize_tls_reloc(bool is_final, int r_type)
{
// If we are generating a shared library, then we can't do anything
// in the linker.
@@ -1774,8 +2086,9 @@ Target_x86_64::optimize_tls_reloc(bool is_final, int r_type)
// Get the Reference_flags for a particular relocation.
+template<int size>
int
-Target_x86_64::Scan::get_reference_flags(unsigned int r_type)
+Target_x86_64<size>::Scan::get_reference_flags(unsigned int r_type)
{
switch (r_type)
{
@@ -1841,9 +2154,10 @@ Target_x86_64::Scan::get_reference_flags(unsigned int r_type)
// Report an unsupported relocation against a local symbol.
+template<int size>
void
-Target_x86_64::Scan::unsupported_reloc_local(
- Sized_relobj_file<64, false>* object,
+Target_x86_64<size>::Scan::unsupported_reloc_local(
+ Sized_relobj_file<size, false>* object,
unsigned int r_type)
{
gold_error(_("%s: unsupported reloc %u against local symbol"),
@@ -1860,9 +2174,10 @@ Target_x86_64::Scan::unsupported_reloc_local(
// it is the symbol the relocation is against; if it is NULL, the
// relocation is against a local symbol.
+template<int size>
void
-Target_x86_64::Scan::check_non_pic(Relobj* object, unsigned int r_type,
- Symbol* gsym)
+Target_x86_64<size>::Scan::check_non_pic(Relobj* object, unsigned int r_type,
+ Symbol* gsym)
{
switch (r_type)
{
@@ -1890,6 +2205,9 @@ Target_x86_64::Scan::check_non_pic(Relobj* object, unsigned int r_type,
return;
/* Fall through. */
case elfcpp::R_X86_64_32:
+ // R_X86_64_32 is OK for x32.
+ if (size == 32 && r_type == elfcpp::R_X86_64_32)
+ return;
if (this->issued_non_pic_error_)
return;
gold_assert(parameters->options().output_is_position_independent());
@@ -1911,10 +2229,10 @@ Target_x86_64::Scan::check_non_pic(Relobj* object, unsigned int r_type,
// section. But we can still wind up issuing more than one
// error per object file.
if (this->issued_non_pic_error_)
- return;
+ return;
gold_assert(parameters->options().output_is_position_independent());
object->error(_("requires unsupported dynamic reloc %u; "
- "recompile with -fPIC"),
+ "recompile with -fPIC"),
r_type);
this->issued_non_pic_error_ = true;
return;
@@ -1927,36 +2245,38 @@ Target_x86_64::Scan::check_non_pic(Relobj* object, unsigned int r_type,
// Return whether we need to make a PLT entry for a relocation of the
// given type against a STT_GNU_IFUNC symbol.
+template<int size>
bool
-Target_x86_64::Scan::reloc_needs_plt_for_ifunc(
- Sized_relobj_file<64, false>* object,
+Target_x86_64<size>::Scan::reloc_needs_plt_for_ifunc(
+ Sized_relobj_file<size, false>* object,
unsigned int r_type)
{
int flags = Scan::get_reference_flags(r_type);
if (flags & Symbol::TLS_REF)
gold_error(_("%s: unsupported TLS reloc %u for IFUNC symbol"),
- object->name().c_str(), r_type);
+ object->name().c_str(), r_type);
return flags != 0;
}
// Scan a relocation for a local symbol.
+template<int size>
inline void
-Target_x86_64::Scan::local(Symbol_table* symtab,
- Layout* layout,
- Target_x86_64* target,
- Sized_relobj_file<64, false>* object,
- unsigned int data_shndx,
- Output_section* output_section,
- const elfcpp::Rela<64, false>& reloc,
- unsigned int r_type,
- const elfcpp::Sym<64, false>& lsym)
+Target_x86_64<size>::Scan::local(Symbol_table* symtab,
+ Layout* layout,
+ Target_x86_64<size>* target,
+ Sized_relobj_file<size, false>* object,
+ unsigned int data_shndx,
+ Output_section* output_section,
+ const elfcpp::Rela<size, false>& reloc,
+ unsigned int r_type,
+ const elfcpp::Sym<size, false>& lsym)
{
// A local STT_GNU_IFUNC symbol may require a PLT entry.
- if (lsym.get_st_type() == elfcpp::STT_GNU_IFUNC
- && this->reloc_needs_plt_for_ifunc(object, r_type))
+ bool is_ifunc = lsym.get_st_type() == elfcpp::STT_GNU_IFUNC;
+ if (is_ifunc && this->reloc_needs_plt_for_ifunc(object, r_type))
{
- unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
target->make_local_ifunc_plt_entry(symtab, layout, object, r_sym);
}
@@ -1975,15 +2295,17 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
// R_X86_64_RELATIVE relocation so the dynamic loader can
// relocate it easily.
if (parameters->options().output_is_position_independent())
- {
- unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
rela_dyn->add_local_relative(object, r_sym,
- elfcpp::R_X86_64_RELATIVE,
+ (size == 32
+ ? elfcpp::R_X86_64_RELATIVE64
+ : elfcpp::R_X86_64_RELATIVE),
output_section, data_shndx,
reloc.get_r_offset(),
- reloc.get_r_addend());
- }
+ reloc.get_r_addend(), is_ifunc);
+ }
break;
case elfcpp::R_X86_64_32:
@@ -1995,18 +2317,31 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
// location. We can't use an R_X86_64_RELATIVE relocation
// because that is always a 64-bit relocation.
if (parameters->options().output_is_position_independent())
- {
- this->check_non_pic(object, r_type, NULL);
+ {
+ // Use R_X86_64_RELATIVE relocation for R_X86_64_32 under x32.
+ if (size == 32 && r_type == elfcpp::R_X86_64_32)
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ rela_dyn->add_local_relative(object, r_sym,
+ elfcpp::R_X86_64_RELATIVE,
+ output_section, data_shndx,
+ reloc.get_r_offset(),
+ reloc.get_r_addend(), is_ifunc);
+ break;
+ }
+
+ this->check_non_pic(object, r_type, NULL);
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
- if (lsym.get_st_type() != elfcpp::STT_SECTION)
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+ if (lsym.get_st_type() != elfcpp::STT_SECTION)
rela_dyn->add_local(object, r_sym, r_type, output_section,
data_shndx, reloc.get_r_offset(),
reloc.get_r_addend());
- else
- {
- gold_assert(lsym.get_st_value() == 0);
+ else
+ {
+ gold_assert(lsym.get_st_value() == 0);
unsigned int shndx = lsym.get_st_shndx();
bool is_ordinary;
shndx = object->adjust_sym_shndx(r_sym, shndx,
@@ -2019,8 +2354,8 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
r_type, output_section,
data_shndx, reloc.get_r_offset(),
reloc.get_r_addend());
- }
- }
+ }
+ }
break;
case elfcpp::R_X86_64_PC64:
@@ -2050,25 +2385,25 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPLT64:
{
- // The symbol requires a GOT entry.
- Output_data_got<64, false>* got = target->got_section(symtab, layout);
- unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
+ // The symbol requires a GOT entry.
+ Output_data_got<64, false>* got = target->got_section(symtab, layout);
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
// For a STT_GNU_IFUNC symbol we want the PLT offset. That
// lets function pointers compare correctly with shared
// libraries. Otherwise we would need an IRELATIVE reloc.
bool is_new;
- if (lsym.get_st_type() == elfcpp::STT_GNU_IFUNC)
+ if (is_ifunc)
is_new = got->add_local_plt(object, r_sym, GOT_TYPE_STANDARD);
else
is_new = got->add_local(object, r_sym, GOT_TYPE_STANDARD);
- if (is_new)
- {
- // If we are generating a shared object, we need to add a
- // dynamic relocation for this symbol's GOT entry.
- if (parameters->options().output_is_position_independent())
- {
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ if (is_new)
+ {
+ // If we are generating a shared object, we need to add a
+ // dynamic relocation for this symbol's GOT entry.
+ if (parameters->options().output_is_position_independent())
+ {
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
// R_X86_64_RELATIVE assumes a 64-bit relocation.
if (r_type != elfcpp::R_X86_64_GOT32)
{
@@ -2076,21 +2411,21 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
rela_dyn->add_local_relative(object, r_sym,
elfcpp::R_X86_64_RELATIVE,
- got, got_offset, 0);
+ got, got_offset, 0, is_ifunc);
}
- else
- {
- this->check_non_pic(object, r_type, NULL);
-
- gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
- rela_dyn->add_local(
- object, r_sym, r_type, got,
- object->local_got_offset(r_sym, GOT_TYPE_STANDARD), 0);
- }
- }
- }
- // For GOTPLT64, we'd normally want a PLT section, but since
- // we know this is a local symbol, no PLT is needed.
+ else
+ {
+ this->check_non_pic(object, r_type, NULL);
+
+ gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
+ rela_dyn->add_local(
+ object, r_sym, r_type, got,
+ object->local_got_offset(r_sym, GOT_TYPE_STANDARD), 0);
+ }
+ }
+ }
+ // For GOTPLT64, we'd normally want a PLT section, but since
+ // we know this is a local symbol, no PLT is needed.
}
break;
@@ -2119,49 +2454,50 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
{
bool output_is_shared = parameters->options().shared();
const tls::Tls_optimization optimized_type
- = Target_x86_64::optimize_tls_reloc(!output_is_shared, r_type);
+ = Target_x86_64<size>::optimize_tls_reloc(!output_is_shared,
+ r_type);
switch (r_type)
{
- case elfcpp::R_X86_64_TLSGD: // General-dynamic
- if (optimized_type == tls::TLSOPT_NONE)
- {
- // Create a pair of GOT entries for the module index and
- // dtv-relative offset.
- Output_data_got<64, false>* got
- = target->got_section(symtab, layout);
- unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
+ case elfcpp::R_X86_64_TLSGD: // General-dynamic
+ if (optimized_type == tls::TLSOPT_NONE)
+ {
+ // Create a pair of GOT entries for the module index and
+ // dtv-relative offset.
+ Output_data_got<64, false>* got
+ = target->got_section(symtab, layout);
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
unsigned int shndx = lsym.get_st_shndx();
bool is_ordinary;
shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
if (!is_ordinary)
object->error(_("local symbol %u has bad shndx %u"),
r_sym, shndx);
- else
- got->add_local_pair_with_rela(object, r_sym,
- shndx,
- GOT_TYPE_TLS_PAIR,
- target->rela_dyn_section(layout),
- elfcpp::R_X86_64_DTPMOD64, 0);
- }
- else if (optimized_type != tls::TLSOPT_TO_LE)
+ else
+ got->add_local_pair_with_rel(object, r_sym,
+ shndx,
+ GOT_TYPE_TLS_PAIR,
+ target->rela_dyn_section(layout),
+ elfcpp::R_X86_64_DTPMOD64, 0);
+ }
+ else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_local(object, r_type);
- break;
+ break;
- case elfcpp::R_X86_64_GOTPC32_TLSDESC:
- target->define_tls_base_symbol(symtab, layout);
+ case elfcpp::R_X86_64_GOTPC32_TLSDESC:
+ target->define_tls_base_symbol(symtab, layout);
if (optimized_type == tls::TLSOPT_NONE)
{
- // Create reserved PLT and GOT entries for the resolver.
- target->reserve_tlsdesc_entries(symtab, layout);
-
- // Generate a double GOT entry with an
- // R_X86_64_TLSDESC reloc. The R_X86_64_TLSDESC reloc
- // is resolved lazily, so the GOT entry needs to be in
- // an area in .got.plt, not .got. Call got_section to
- // make sure the section has been created.
+ // Create reserved PLT and GOT entries for the resolver.
+ target->reserve_tlsdesc_entries(symtab, layout);
+
+ // Generate a double GOT entry with an
+ // R_X86_64_TLSDESC reloc. The R_X86_64_TLSDESC reloc
+ // is resolved lazily, so the GOT entry needs to be in
+ // an area in .got.plt, not .got. Call got_section to
+ // make sure the section has been created.
target->got_section(symtab, layout);
- Output_data_got<64, false>* got = target->got_tlsdesc_section();
- unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
+ Output_data_got<64, false>* got = target->got_tlsdesc_section();
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_DESC))
{
unsigned int got_offset = got->add_constant(0);
@@ -2182,47 +2518,47 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
unsupported_reloc_local(object, r_type);
break;
- case elfcpp::R_X86_64_TLSDESC_CALL:
+ case elfcpp::R_X86_64_TLSDESC_CALL:
break;
- case elfcpp::R_X86_64_TLSLD: // Local-dynamic
+ case elfcpp::R_X86_64_TLSLD: // Local-dynamic
if (optimized_type == tls::TLSOPT_NONE)
{
- // Create a GOT entry for the module index.
- target->got_mod_index_entry(symtab, layout, object);
+ // Create a GOT entry for the module index.
+ target->got_mod_index_entry(symtab, layout, object);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_local(object, r_type);
break;
- case elfcpp::R_X86_64_DTPOFF32:
- case elfcpp::R_X86_64_DTPOFF64:
+ case elfcpp::R_X86_64_DTPOFF32:
+ case elfcpp::R_X86_64_DTPOFF64:
break;
- case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec
+ case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec
layout->set_has_static_tls();
- if (optimized_type == tls::TLSOPT_NONE)
- {
- // Create a GOT entry for the tp-relative offset.
- Output_data_got<64, false>* got
- = target->got_section(symtab, layout);
- unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
- got->add_local_with_rela(object, r_sym, GOT_TYPE_TLS_OFFSET,
- target->rela_dyn_section(layout),
- elfcpp::R_X86_64_TPOFF64);
- }
- else if (optimized_type != tls::TLSOPT_TO_LE)
- unsupported_reloc_local(object, r_type);
- break;
-
- case elfcpp::R_X86_64_TPOFF32: // Local-exec
+ if (optimized_type == tls::TLSOPT_NONE)
+ {
+ // Create a GOT entry for the tp-relative offset.
+ Output_data_got<64, false>* got
+ = target->got_section(symtab, layout);
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
+ got->add_local_with_rel(object, r_sym, GOT_TYPE_TLS_OFFSET,
+ target->rela_dyn_section(layout),
+ elfcpp::R_X86_64_TPOFF64);
+ }
+ else if (optimized_type != tls::TLSOPT_TO_LE)
+ unsupported_reloc_local(object, r_type);
+ break;
+
+ case elfcpp::R_X86_64_TPOFF32: // Local-exec
layout->set_has_static_tls();
- if (output_is_shared)
- unsupported_reloc_local(object, r_type);
+ if (output_is_shared)
+ unsupported_reloc_local(object, r_type);
break;
- default:
- gold_unreachable();
+ default:
+ gold_unreachable();
}
}
break;
@@ -2239,9 +2575,10 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
// Report an unsupported relocation against a global symbol.
+template<int size>
void
-Target_x86_64::Scan::unsupported_reloc_global(
- Sized_relobj_file<64, false>* object,
+Target_x86_64<size>::Scan::unsupported_reloc_global(
+ Sized_relobj_file<size, false>* object,
unsigned int r_type,
Symbol* gsym)
{
@@ -2250,8 +2587,9 @@ Target_x86_64::Scan::unsupported_reloc_global(
}
// Returns true if this relocation type could be that of a function pointer.
+template<int size>
inline bool
-Target_x86_64::Scan::possible_function_pointer_reloc(unsigned int r_type)
+Target_x86_64<size>::Scan::possible_function_pointer_reloc(unsigned int r_type)
{
switch (r_type)
{
@@ -2266,7 +2604,7 @@ Target_x86_64::Scan::possible_function_pointer_reloc(unsigned int r_type)
case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPLT64:
{
- return true;
+ return true;
}
}
return false;
@@ -2276,62 +2614,65 @@ Target_x86_64::Scan::possible_function_pointer_reloc(unsigned int r_type)
// corresponds to a function pointer being taken. In that case mark
// the function whose pointer was taken as not foldable.
+template<int size>
inline bool
-Target_x86_64::Scan::local_reloc_may_be_function_pointer(
+Target_x86_64<size>::Scan::local_reloc_may_be_function_pointer(
Symbol_table* ,
Layout* ,
- Target_x86_64* ,
- Sized_relobj_file<64, false>* ,
+ Target_x86_64<size>* ,
+ Sized_relobj_file<size, false>* ,
unsigned int ,
Output_section* ,
- const elfcpp::Rela<64, false>& ,
+ const elfcpp::Rela<size, false>& ,
unsigned int r_type,
- const elfcpp::Sym<64, false>&)
+ const elfcpp::Sym<size, false>&)
{
// When building a shared library, do not fold any local symbols as it is
// not possible to distinguish pointer taken versus a call by looking at
// the relocation types.
return (parameters->options().shared()
- || possible_function_pointer_reloc(r_type));
+ || possible_function_pointer_reloc(r_type));
}
// For safe ICF, scan a relocation for a global symbol to check if it
// corresponds to a function pointer being taken. In that case mark
// the function whose pointer was taken as not foldable.
+template<int size>
inline bool
-Target_x86_64::Scan::global_reloc_may_be_function_pointer(
+Target_x86_64<size>::Scan::global_reloc_may_be_function_pointer(
Symbol_table*,
Layout* ,
- Target_x86_64* ,
- Sized_relobj_file<64, false>* ,
+ Target_x86_64<size>* ,
+ Sized_relobj_file<size, false>* ,
unsigned int ,
Output_section* ,
- const elfcpp::Rela<64, false>& ,
+ const elfcpp::Rela<size, false>& ,
unsigned int r_type,
Symbol* gsym)
{
// When building a shared library, do not fold symbols whose visibility
// is hidden, internal or protected.
return ((parameters->options().shared()
- && (gsym->visibility() == elfcpp::STV_INTERNAL
+ && (gsym->visibility() == elfcpp::STV_INTERNAL
|| gsym->visibility() == elfcpp::STV_PROTECTED
|| gsym->visibility() == elfcpp::STV_HIDDEN))
- || possible_function_pointer_reloc(r_type));
+ || possible_function_pointer_reloc(r_type));
}
// Scan a relocation for a global symbol.
+template<int size>
inline void
-Target_x86_64::Scan::global(Symbol_table* symtab,
- Layout* layout,
- Target_x86_64* target,
- Sized_relobj_file<64, false>* object,
- unsigned int data_shndx,
- Output_section* output_section,
- const elfcpp::Rela<64, false>& reloc,
- unsigned int r_type,
- Symbol* gsym)
+Target_x86_64<size>::Scan::global(Symbol_table* symtab,
+ Layout* layout,
+ Target_x86_64<size>* target,
+ Sized_relobj_file<size, false>* object,
+ unsigned int data_shndx,
+ Output_section* output_section,
+ const elfcpp::Rela<size, false>& reloc,
+ unsigned int r_type,
+ Symbol* gsym)
{
// A STT_GNU_IFUNC symbol may require a PLT entry.
if (gsym->type() == elfcpp::STT_GNU_IFUNC
@@ -2351,26 +2692,27 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
case elfcpp::R_X86_64_16:
case elfcpp::R_X86_64_8:
{
- // Make a PLT entry if necessary.
- if (gsym->needs_plt_entry())
- {
- target->make_plt_entry(symtab, layout, gsym);
- // Since this is not a PC-relative relocation, we may be
- // taking the address of a function. In that case we need to
- // set the entry in the dynamic symbol table to the address of
- // the PLT entry.
- if (gsym->is_from_dynobj() && !parameters->options().shared())
- gsym->set_needs_dynsym_value();
- }
- // Make a dynamic relocation if necessary.
- if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
- {
- if (gsym->may_need_copy_reloc())
- {
- target->copy_reloc(symtab, layout, object,
- data_shndx, output_section, gsym, reloc);
- }
- else if (r_type == elfcpp::R_X86_64_64
+ // Make a PLT entry if necessary.
+ if (gsym->needs_plt_entry())
+ {
+ target->make_plt_entry(symtab, layout, gsym);
+ // Since this is not a PC-relative relocation, we may be
+ // taking the address of a function. In that case we need to
+ // set the entry in the dynamic symbol table to the address of
+ // the PLT entry.
+ if (gsym->is_from_dynobj() && !parameters->options().shared())
+ gsym->set_needs_dynsym_value();
+ }
+ // Make a dynamic relocation if necessary.
+ if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
+ {
+ if (gsym->may_need_copy_reloc())
+ {
+ target->copy_reloc(symtab, layout, object,
+ data_shndx, output_section, gsym, reloc);
+ }
+ else if (((size == 64 && r_type == elfcpp::R_X86_64_64)
+ || (size == 32 && r_type == elfcpp::R_X86_64_32))
&& gsym->type() == elfcpp::STT_GNU_IFUNC
&& gsym->can_use_relative_reloc(false)
&& !gsym->is_from_dynobj()
@@ -2390,25 +2732,25 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
reloc.get_r_offset(),
reloc.get_r_addend());
}
- else if (r_type == elfcpp::R_X86_64_64
- && gsym->can_use_relative_reloc(false))
- {
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ else if (r_type == elfcpp::R_X86_64_64
+ && gsym->can_use_relative_reloc(false))
+ {
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_RELATIVE,
output_section, object,
data_shndx,
reloc.get_r_offset(),
- reloc.get_r_addend());
- }
- else
- {
- this->check_non_pic(object, r_type, gsym);
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- rela_dyn->add_global(gsym, r_type, output_section, object,
- data_shndx, reloc.get_r_offset(),
- reloc.get_r_addend());
- }
- }
+ reloc.get_r_addend(), false);
+ }
+ else
+ {
+ this->check_non_pic(object, r_type, gsym);
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ rela_dyn->add_global(gsym, r_type, output_section, object,
+ data_shndx, reloc.get_r_offset(),
+ reloc.get_r_addend());
+ }
+ }
}
break;
@@ -2417,26 +2759,26 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
case elfcpp::R_X86_64_PC16:
case elfcpp::R_X86_64_PC8:
{
- // Make a PLT entry if necessary.
- if (gsym->needs_plt_entry())
- target->make_plt_entry(symtab, layout, gsym);
- // Make a dynamic relocation if necessary.
- if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
- {
- if (gsym->may_need_copy_reloc())
- {
- target->copy_reloc(symtab, layout, object,
- data_shndx, output_section, gsym, reloc);
- }
- else
- {
- this->check_non_pic(object, r_type, gsym);
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- rela_dyn->add_global(gsym, r_type, output_section, object,
- data_shndx, reloc.get_r_offset(),
- reloc.get_r_addend());
- }
- }
+ // Make a PLT entry if necessary.
+ if (gsym->needs_plt_entry())
+ target->make_plt_entry(symtab, layout, gsym);
+ // Make a dynamic relocation if necessary.
+ if (gsym->needs_dynamic_reloc(Scan::get_reference_flags(r_type)))
+ {
+ if (gsym->may_need_copy_reloc())
+ {
+ target->copy_reloc(symtab, layout, object,
+ data_shndx, output_section, gsym, reloc);
+ }
+ else
+ {
+ this->check_non_pic(object, r_type, gsym);
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ rela_dyn->add_global(gsym, r_type, output_section, object,
+ data_shndx, reloc.get_r_offset(),
+ reloc.get_r_addend());
+ }
+ }
}
break;
@@ -2446,9 +2788,9 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPLT64:
{
- // The symbol requires a GOT entry.
- Output_data_got<64, false>* got = target->got_section(symtab, layout);
- if (gsym->final_value_is_known())
+ // The symbol requires a GOT entry.
+ Output_data_got<64, false>* got = target->got_section(symtab, layout);
+ if (gsym->final_value_is_known())
{
// For a STT_GNU_IFUNC symbol we want the PLT address.
if (gsym->type() == elfcpp::STT_GNU_IFUNC)
@@ -2456,11 +2798,11 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
else
got->add_global(gsym, GOT_TYPE_STANDARD);
}
- else
- {
- // If this symbol is not fully resolved, we need to add a
- // dynamic relocation for it.
- Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ else
+ {
+ // If this symbol is not fully resolved, we need to add a
+ // dynamic relocation for it.
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
// Use a GLOB_DAT rather than a RELATIVE reloc if:
//
@@ -2481,10 +2823,10 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
&& parameters->options().shared())
|| (gsym->type() == elfcpp::STT_GNU_IFUNC
&& parameters->options().output_is_position_independent()))
- got->add_global_with_rela(gsym, GOT_TYPE_STANDARD, rela_dyn,
- elfcpp::R_X86_64_GLOB_DAT);
- else
- {
+ got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, rela_dyn,
+ elfcpp::R_X86_64_GLOB_DAT);
+ else
+ {
// For a STT_GNU_IFUNC symbol we want to write the PLT
// offset into the GOT, so that function pointer
// comparisons work correctly.
@@ -2500,20 +2842,20 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
&& !parameters->options().shared())
gsym->set_needs_dynsym_value();
}
- if (is_new)
+ if (is_new)
{
unsigned int got_off = gsym->got_offset(GOT_TYPE_STANDARD);
rela_dyn->add_global_relative(gsym,
elfcpp::R_X86_64_RELATIVE,
- got, got_off, 0);
+ got, got_off, 0, false);
}
- }
- }
- // For GOTPLT64, we also need a PLT entry (but only if the
- // symbol is not fully resolved).
- if (r_type == elfcpp::R_X86_64_GOTPLT64
- && !gsym->final_value_is_known())
- target->make_plt_entry(symtab, layout, gsym);
+ }
+ }
+ // For GOTPLT64, we also need a PLT entry (but only if the
+ // symbol is not fully resolved).
+ if (r_type == elfcpp::R_X86_64_GOTPLT64
+ && !gsym->final_value_is_known())
+ target->make_plt_entry(symtab, layout, gsym);
}
break;
@@ -2526,8 +2868,8 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
// if the symbol is defined in the output file and is protected
// or hidden.
if (gsym->is_defined()
- && !gsym->is_from_dynobj()
- && !gsym->is_preemptible())
+ && !gsym->is_from_dynobj()
+ && !gsym->is_preemptible())
break;
target->make_plt_entry(symtab, layout, gsym);
break;
@@ -2570,105 +2912,105 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
{
const bool is_final = gsym->final_value_is_known();
const tls::Tls_optimization optimized_type
- = Target_x86_64::optimize_tls_reloc(is_final, r_type);
+ = Target_x86_64<size>::optimize_tls_reloc(is_final, r_type);
switch (r_type)
{
- case elfcpp::R_X86_64_TLSGD: // General-dynamic
+ case elfcpp::R_X86_64_TLSGD: // General-dynamic
if (optimized_type == tls::TLSOPT_NONE)
{
- // Create a pair of GOT entries for the module index and
- // dtv-relative offset.
- Output_data_got<64, false>* got
- = target->got_section(symtab, layout);
- got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_PAIR,
- target->rela_dyn_section(layout),
- elfcpp::R_X86_64_DTPMOD64,
- elfcpp::R_X86_64_DTPOFF64);
+ // Create a pair of GOT entries for the module index and
+ // dtv-relative offset.
+ Output_data_got<64, false>* got
+ = target->got_section(symtab, layout);
+ got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
+ target->rela_dyn_section(layout),
+ elfcpp::R_X86_64_DTPMOD64,
+ elfcpp::R_X86_64_DTPOFF64);
}
else if (optimized_type == tls::TLSOPT_TO_IE)
{
- // Create a GOT entry for the tp-relative offset.
- Output_data_got<64, false>* got
- = target->got_section(symtab, layout);
- got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET,
- target->rela_dyn_section(layout),
- elfcpp::R_X86_64_TPOFF64);
+ // Create a GOT entry for the tp-relative offset.
+ Output_data_got<64, false>* got
+ = target->got_section(symtab, layout);
+ got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
+ target->rela_dyn_section(layout),
+ elfcpp::R_X86_64_TPOFF64);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_global(object, r_type, gsym);
break;
- case elfcpp::R_X86_64_GOTPC32_TLSDESC:
- target->define_tls_base_symbol(symtab, layout);
+ case elfcpp::R_X86_64_GOTPC32_TLSDESC:
+ target->define_tls_base_symbol(symtab, layout);
if (optimized_type == tls::TLSOPT_NONE)
{
- // Create reserved PLT and GOT entries for the resolver.
- target->reserve_tlsdesc_entries(symtab, layout);
-
- // Create a double GOT entry with an R_X86_64_TLSDESC
- // reloc. The R_X86_64_TLSDESC reloc is resolved
- // lazily, so the GOT entry needs to be in an area in
- // .got.plt, not .got. Call got_section to make sure
- // the section has been created.
+ // Create reserved PLT and GOT entries for the resolver.
+ target->reserve_tlsdesc_entries(symtab, layout);
+
+ // Create a double GOT entry with an R_X86_64_TLSDESC
+ // reloc. The R_X86_64_TLSDESC reloc is resolved
+ // lazily, so the GOT entry needs to be in an area in
+ // .got.plt, not .got. Call got_section to make sure
+ // the section has been created.
target->got_section(symtab, layout);
- Output_data_got<64, false>* got = target->got_tlsdesc_section();
+ Output_data_got<64, false>* got = target->got_tlsdesc_section();
Reloc_section* rt = target->rela_tlsdesc_section(layout);
- got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_DESC, rt,
- elfcpp::R_X86_64_TLSDESC, 0);
+ got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC, rt,
+ elfcpp::R_X86_64_TLSDESC, 0);
}
else if (optimized_type == tls::TLSOPT_TO_IE)
{
- // Create a GOT entry for the tp-relative offset.
- Output_data_got<64, false>* got
- = target->got_section(symtab, layout);
- got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET,
- target->rela_dyn_section(layout),
- elfcpp::R_X86_64_TPOFF64);
+ // Create a GOT entry for the tp-relative offset.
+ Output_data_got<64, false>* got
+ = target->got_section(symtab, layout);
+ got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
+ target->rela_dyn_section(layout),
+ elfcpp::R_X86_64_TPOFF64);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_global(object, r_type, gsym);
break;
- case elfcpp::R_X86_64_TLSDESC_CALL:
+ case elfcpp::R_X86_64_TLSDESC_CALL:
break;
- case elfcpp::R_X86_64_TLSLD: // Local-dynamic
+ case elfcpp::R_X86_64_TLSLD: // Local-dynamic
if (optimized_type == tls::TLSOPT_NONE)
{
- // Create a GOT entry for the module index.
- target->got_mod_index_entry(symtab, layout, object);
+ // Create a GOT entry for the module index.
+ target->got_mod_index_entry(symtab, layout, object);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_global(object, r_type, gsym);
break;
- case elfcpp::R_X86_64_DTPOFF32:
- case elfcpp::R_X86_64_DTPOFF64:
+ case elfcpp::R_X86_64_DTPOFF32:
+ case elfcpp::R_X86_64_DTPOFF64:
break;
- case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec
+ case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec
layout->set_has_static_tls();
- if (optimized_type == tls::TLSOPT_NONE)
- {
- // Create a GOT entry for the tp-relative offset.
- Output_data_got<64, false>* got
- = target->got_section(symtab, layout);
- got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET,
- target->rela_dyn_section(layout),
- elfcpp::R_X86_64_TPOFF64);
- }
- else if (optimized_type != tls::TLSOPT_TO_LE)
- unsupported_reloc_global(object, r_type, gsym);
- break;
-
- case elfcpp::R_X86_64_TPOFF32: // Local-exec
+ if (optimized_type == tls::TLSOPT_NONE)
+ {
+ // Create a GOT entry for the tp-relative offset.
+ Output_data_got<64, false>* got
+ = target->got_section(symtab, layout);
+ got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
+ target->rela_dyn_section(layout),
+ elfcpp::R_X86_64_TPOFF64);
+ }
+ else if (optimized_type != tls::TLSOPT_TO_LE)
+ unsupported_reloc_global(object, r_type, gsym);
+ break;
+
+ case elfcpp::R_X86_64_TPOFF32: // Local-exec
layout->set_has_static_tls();
- if (parameters->options().shared())
- unsupported_reloc_local(object, r_type);
+ if (parameters->options().shared())
+ unsupported_reloc_local(object, r_type);
break;
- default:
- gold_unreachable();
+ default:
+ gold_unreachable();
}
}
break;
@@ -2678,23 +3020,24 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
default:
gold_error(_("%s: unsupported reloc %u against global symbol %s"),
object->name().c_str(), r_type,
- gsym->demangled_name().c_str());
+ gsym->demangled_name().c_str());
break;
}
}
+template<int size>
void
-Target_x86_64::gc_process_relocs(Symbol_table* symtab,
- Layout* layout,
- Sized_relobj_file<64, false>* object,
- unsigned int data_shndx,
- unsigned int sh_type,
- const unsigned char* prelocs,
- size_t reloc_count,
- Output_section* output_section,
- bool needs_special_offset_handling,
- size_t local_symbol_count,
- const unsigned char* plocal_symbols)
+Target_x86_64<size>::gc_process_relocs(Symbol_table* symtab,
+ Layout* layout,
+ Sized_relobj_file<size, false>* object,
+ unsigned int data_shndx,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ size_t local_symbol_count,
+ const unsigned char* plocal_symbols)
{
if (sh_type == elfcpp::SHT_REL)
@@ -2702,9 +3045,9 @@ Target_x86_64::gc_process_relocs(Symbol_table* symtab,
return;
}
- gold::gc_process_relocs<64, false, Target_x86_64, elfcpp::SHT_RELA,
- Target_x86_64::Scan,
- Target_x86_64::Relocatable_size_for_reloc>(
+ gold::gc_process_relocs<size, false, Target_x86_64<size>, elfcpp::SHT_RELA,
+ typename Target_x86_64<size>::Scan,
+ typename Target_x86_64<size>::Relocatable_size_for_reloc>(
symtab,
layout,
this,
@@ -2716,22 +3059,23 @@ Target_x86_64::gc_process_relocs(Symbol_table* symtab,
needs_special_offset_handling,
local_symbol_count,
plocal_symbols);
-
+
}
// Scan relocations for a section.
+template<int size>
void
-Target_x86_64::scan_relocs(Symbol_table* symtab,
- Layout* layout,
- Sized_relobj_file<64, false>* object,
- unsigned int data_shndx,
- unsigned int sh_type,
- const unsigned char* prelocs,
- size_t reloc_count,
- Output_section* output_section,
- bool needs_special_offset_handling,
- size_t local_symbol_count,
- const unsigned char* plocal_symbols)
+Target_x86_64<size>::scan_relocs(Symbol_table* symtab,
+ Layout* layout,
+ Sized_relobj_file<size, false>* object,
+ unsigned int data_shndx,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ size_t local_symbol_count,
+ const unsigned char* plocal_symbols)
{
if (sh_type == elfcpp::SHT_REL)
{
@@ -2740,8 +3084,8 @@ Target_x86_64::scan_relocs(Symbol_table* symtab,
return;
}
- gold::scan_relocs<64, false, Target_x86_64, elfcpp::SHT_RELA,
- Target_x86_64::Scan>(
+ gold::scan_relocs<size, false, Target_x86_64<size>, elfcpp::SHT_RELA,
+ typename Target_x86_64<size>::Scan>(
symtab,
layout,
this,
@@ -2757,8 +3101,9 @@ Target_x86_64::scan_relocs(Symbol_table* symtab,
// Finalize the sections.
+template<int size>
void
-Target_x86_64::do_finalize_sections(
+Target_x86_64<size>::do_finalize_sections(
Layout* layout,
const Input_objects*,
Symbol_table* symtab)
@@ -2768,7 +3113,7 @@ Target_x86_64::do_finalize_sections(
: this->plt_->rela_plt());
layout->add_target_dynamic_tags(false, this->got_plt_, rel_plt,
this->rela_dyn_, true, false);
-
+
// Fill in some more dynamic tags.
Output_data_dynamic* const odyn = layout->dynamic_data();
if (odyn != NULL)
@@ -2798,7 +3143,7 @@ Target_x86_64::do_finalize_sections(
if (sym != NULL)
{
uint64_t data_size = this->got_plt_->current_data_size();
- symtab->get_sized_symbol<64>(sym)->set_symsize(data_size);
+ symtab->get_sized_symbol<size>(sym)->set_symsize(data_size);
}
if (parameters->doing_static_link()
@@ -2845,23 +3190,25 @@ Target_x86_64::do_finalize_sections(
// Perform a relocation.
+template<int size>
inline bool
-Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
- Target_x86_64* target,
- Output_section*,
- size_t relnum,
- const elfcpp::Rela<64, false>& rela,
- unsigned int r_type,
- const Sized_symbol<64>* gsym,
- const Symbol_value<64>* psymval,
- unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr address,
- section_size_type view_size)
+Target_x86_64<size>::Relocate::relocate(
+ const Relocate_info<size, false>* relinfo,
+ Target_x86_64<size>* target,
+ Output_section*,
+ size_t relnum,
+ const elfcpp::Rela<size, false>& rela,
+ unsigned int r_type,
+ const Sized_symbol<size>* gsym,
+ const Symbol_value<size>* psymval,
+ unsigned char* view,
+ typename elfcpp::Elf_types<size>::Elf_Addr address,
+ section_size_type view_size)
{
if (this->skip_call_tls_get_addr_)
{
if ((r_type != elfcpp::R_X86_64_PLT32
- && r_type != elfcpp::R_X86_64_PC32)
+ && r_type != elfcpp::R_X86_64_PC32)
|| gsym == NULL
|| strcmp(gsym->name(), "__tls_get_addr") != 0)
{
@@ -2875,10 +3222,10 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
}
}
- const Sized_relobj_file<64, false>* object = relinfo->object;
+ const Sized_relobj_file<size, false>* object = relinfo->object;
// Pick the value to use for symbols defined in the PLT.
- Symbol_value<64> symval;
+ Symbol_value<size> symval;
if (gsym != NULL
&& gsym->use_plt_offset(Scan::get_reference_flags(r_type)))
{
@@ -2888,7 +3235,7 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
}
else if (gsym == NULL && psymval->is_ifunc_symbol())
{
- unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
if (object->local_has_plt_offset(r_sym))
{
symval.set_output_value(target->plt_address_for_local(object, r_sym)
@@ -2913,17 +3260,17 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPCREL64:
if (gsym != NULL)
- {
- gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
- got_offset = gsym->got_offset(GOT_TYPE_STANDARD) - target->got_size();
- }
+ {
+ gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
+ got_offset = gsym->got_offset(GOT_TYPE_STANDARD) - target->got_size();
+ }
else
- {
- unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
- got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
- - target->got_size());
- }
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+ gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
+ got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
+ - target->got_size());
+ }
have_got_offset = true;
break;
@@ -2939,12 +3286,12 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
break;
case elfcpp::R_X86_64_64:
- Relocate_functions<64, false>::rela64(view, object, psymval, addend);
+ Relocate_functions<size, false>::rela64(view, object, psymval, addend);
break;
case elfcpp::R_X86_64_PC64:
- Relocate_functions<64, false>::pcrela64(view, object, psymval, addend,
- address);
+ Relocate_functions<size, false>::pcrela64(view, object, psymval, addend,
+ address);
break;
case elfcpp::R_X86_64_32:
@@ -2952,42 +3299,42 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
// uint64_t x = value + addend;
// x == static_cast<uint64_t>(static_cast<uint32_t>(x))
// Likewise for other <=32-bit relocations (but see R_X86_64_32S).
- Relocate_functions<64, false>::rela32(view, object, psymval, addend);
+ Relocate_functions<size, false>::rela32(view, object, psymval, addend);
break;
case elfcpp::R_X86_64_32S:
// FIXME: we need to verify that value + addend fits into 32 bits:
// int64_t x = value + addend; // note this quantity is signed!
// x == static_cast<int64_t>(static_cast<int32_t>(x))
- Relocate_functions<64, false>::rela32(view, object, psymval, addend);
+ Relocate_functions<size, false>::rela32(view, object, psymval, addend);
break;
case elfcpp::R_X86_64_PC32:
- Relocate_functions<64, false>::pcrela32(view, object, psymval, addend,
- address);
+ Relocate_functions<size, false>::pcrela32(view, object, psymval, addend,
+ address);
break;
case elfcpp::R_X86_64_16:
- Relocate_functions<64, false>::rela16(view, object, psymval, addend);
+ Relocate_functions<size, false>::rela16(view, object, psymval, addend);
break;
case elfcpp::R_X86_64_PC16:
- Relocate_functions<64, false>::pcrela16(view, object, psymval, addend,
- address);
+ Relocate_functions<size, false>::pcrela16(view, object, psymval, addend,
+ address);
break;
case elfcpp::R_X86_64_8:
- Relocate_functions<64, false>::rela8(view, object, psymval, addend);
+ Relocate_functions<size, false>::rela8(view, object, psymval, addend);
break;
case elfcpp::R_X86_64_PC8:
- Relocate_functions<64, false>::pcrela8(view, object, psymval, addend,
- address);
+ Relocate_functions<size, false>::pcrela8(view, object, psymval, addend,
+ address);
break;
case elfcpp::R_X86_64_PLT32:
gold_assert(gsym == NULL
- || gsym->has_plt_offset()
+ || gsym->has_plt_offset()
|| gsym->final_value_is_known()
|| (gsym->is_defined()
&& !gsym->is_from_dynobj()
@@ -2995,32 +3342,32 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
// Note: while this code looks the same as for R_X86_64_PC32, it
// behaves differently because psymval was set to point to
// the PLT entry, rather than the symbol, in Scan::global().
- Relocate_functions<64, false>::pcrela32(view, object, psymval, addend,
- address);
+ Relocate_functions<size, false>::pcrela32(view, object, psymval, addend,
+ address);
break;
case elfcpp::R_X86_64_PLTOFF64:
{
- gold_assert(gsym);
- gold_assert(gsym->has_plt_offset()
- || gsym->final_value_is_known());
- elfcpp::Elf_types<64>::Elf_Addr got_address;
+ gold_assert(gsym);
+ gold_assert(gsym->has_plt_offset()
+ || gsym->final_value_is_known());
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address;
got_address = target->got_section(NULL, NULL)->address();
- Relocate_functions<64, false>::rela64(view, object, psymval,
- addend - got_address);
+ Relocate_functions<size, false>::rela64(view, object, psymval,
+ addend - got_address);
}
case elfcpp::R_X86_64_GOT32:
gold_assert(have_got_offset);
- Relocate_functions<64, false>::rela32(view, got_offset, addend);
+ Relocate_functions<size, false>::rela32(view, got_offset, addend);
break;
case elfcpp::R_X86_64_GOTPC32:
{
- gold_assert(gsym);
- elfcpp::Elf_types<64>::Elf_Addr value;
+ gold_assert(gsym);
+ typename elfcpp::Elf_types<size>::Elf_Addr value;
value = target->got_plt_section()->address();
- Relocate_functions<64, false>::pcrela32(view, value, addend, address);
+ Relocate_functions<size, false>::pcrela32(view, value, addend, address);
}
break;
@@ -3029,42 +3376,42 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
// Since we always add a PLT entry, this is equivalent.
case elfcpp::R_X86_64_GOTPLT64:
gold_assert(have_got_offset);
- Relocate_functions<64, false>::rela64(view, got_offset, addend);
+ Relocate_functions<size, false>::rela64(view, got_offset, addend);
break;
case elfcpp::R_X86_64_GOTPC64:
{
- gold_assert(gsym);
- elfcpp::Elf_types<64>::Elf_Addr value;
+ gold_assert(gsym);
+ typename elfcpp::Elf_types<size>::Elf_Addr value;
value = target->got_plt_section()->address();
- Relocate_functions<64, false>::pcrela64(view, value, addend, address);
+ Relocate_functions<size, false>::pcrela64(view, value, addend, address);
}
break;
case elfcpp::R_X86_64_GOTOFF64:
{
- elfcpp::Elf_types<64>::Elf_Addr value;
+ typename elfcpp::Elf_types<size>::Elf_Addr value;
value = (psymval->value(object, 0)
- target->got_plt_section()->address());
- Relocate_functions<64, false>::rela64(view, value, addend);
+ Relocate_functions<size, false>::rela64(view, value, addend);
}
break;
case elfcpp::R_X86_64_GOTPCREL:
{
- gold_assert(have_got_offset);
- elfcpp::Elf_types<64>::Elf_Addr value;
- value = target->got_plt_section()->address() + got_offset;
- Relocate_functions<64, false>::pcrela32(view, value, addend, address);
+ gold_assert(have_got_offset);
+ typename elfcpp::Elf_types<size>::Elf_Addr value;
+ value = target->got_plt_section()->address() + got_offset;
+ Relocate_functions<size, false>::pcrela32(view, value, addend, address);
}
break;
case elfcpp::R_X86_64_GOTPCREL64:
{
- gold_assert(have_got_offset);
- elfcpp::Elf_types<64>::Elf_Addr value;
- value = target->got_plt_section()->address() + got_offset;
- Relocate_functions<64, false>::pcrela64(view, value, addend, address);
+ gold_assert(have_got_offset);
+ typename elfcpp::Elf_types<size>::Elf_Addr value;
+ value = target->got_plt_section()->address() + got_offset;
+ Relocate_functions<size, false>::pcrela64(view, value, addend, address);
}
break;
@@ -3092,7 +3439,7 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec
case elfcpp::R_X86_64_TPOFF32: // Local-exec
this->relocate_tls(relinfo, target, relnum, rela, r_type, gsym, psymval,
- view, address, view_size);
+ view, address, view_size);
break;
case elfcpp::R_X86_64_SIZE32:
@@ -3109,32 +3456,34 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
// Perform a TLS relocation.
+template<int size>
inline void
-Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
- Target_x86_64* target,
- size_t relnum,
- const elfcpp::Rela<64, false>& rela,
- unsigned int r_type,
- const Sized_symbol<64>* gsym,
- const Symbol_value<64>* psymval,
- unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr address,
- section_size_type view_size)
+Target_x86_64<size>::Relocate::relocate_tls(
+ const Relocate_info<size, false>* relinfo,
+ Target_x86_64<size>* target,
+ size_t relnum,
+ const elfcpp::Rela<size, false>& rela,
+ unsigned int r_type,
+ const Sized_symbol<size>* gsym,
+ const Symbol_value<size>* psymval,
+ unsigned char* view,
+ typename elfcpp::Elf_types<size>::Elf_Addr address,
+ section_size_type view_size)
{
Output_segment* tls_segment = relinfo->layout->tls_segment();
- const Sized_relobj_file<64, false>* object = relinfo->object;
+ const Sized_relobj_file<size, false>* object = relinfo->object;
const elfcpp::Elf_Xword addend = rela.get_r_addend();
- elfcpp::Shdr<64, false> data_shdr(relinfo->data_shdr);
+ elfcpp::Shdr<size, false> data_shdr(relinfo->data_shdr);
bool is_executable = (data_shdr.get_sh_flags() & elfcpp::SHF_EXECINSTR) != 0;
- elfcpp::Elf_types<64>::Elf_Addr value = psymval->value(relinfo->object, 0);
+ typename elfcpp::Elf_types<size>::Elf_Addr value = psymval->value(relinfo->object, 0);
const bool is_final = (gsym == NULL
? !parameters->options().shared()
: gsym->final_value_is_known());
tls::Tls_optimization optimized_type
- = Target_x86_64::optimize_tls_reloc(is_final, r_type);
+ = Target_x86_64<size>::optimize_tls_reloc(is_final, r_type);
switch (r_type)
{
case elfcpp::R_X86_64_TLSGD: // Global-dynamic
@@ -3162,46 +3511,40 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
break;
}
else
- {
- unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
- ? GOT_TYPE_TLS_OFFSET
- : GOT_TYPE_TLS_PAIR);
- unsigned int got_offset;
- if (gsym != NULL)
- {
- gold_assert(gsym->has_got_offset(got_type));
- got_offset = gsym->got_offset(got_type) - target->got_size();
- }
- else
- {
- unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym, got_type));
- got_offset = (object->local_got_offset(r_sym, got_type)
- - target->got_size());
- }
- if (optimized_type == tls::TLSOPT_TO_IE)
- {
- if (tls_segment == NULL)
- {
- gold_assert(parameters->errors()->error_count() > 0
- || issue_undefined_symbol_error(gsym));
- return;
- }
- value = target->got_plt_section()->address() + got_offset;
- this->tls_gd_to_ie(relinfo, relnum, tls_segment, rela, r_type,
- value, view, address, view_size);
- break;
- }
- else if (optimized_type == tls::TLSOPT_NONE)
- {
- // Relocate the field with the offset of the pair of GOT
- // entries.
+ {
+ unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
+ ? GOT_TYPE_TLS_OFFSET
+ : GOT_TYPE_TLS_PAIR);
+ unsigned int got_offset;
+ if (gsym != NULL)
+ {
+ gold_assert(gsym->has_got_offset(got_type));
+ got_offset = gsym->got_offset(got_type) - target->got_size();
+ }
+ else
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+ gold_assert(object->local_has_got_offset(r_sym, got_type));
+ got_offset = (object->local_got_offset(r_sym, got_type)
+ - target->got_size());
+ }
+ if (optimized_type == tls::TLSOPT_TO_IE)
+ {
value = target->got_plt_section()->address() + got_offset;
- Relocate_functions<64, false>::pcrela32(view, value, addend,
- address);
- break;
- }
- }
+ this->tls_gd_to_ie(relinfo, relnum, tls_segment, rela, r_type,
+ value, view, address, view_size);
+ break;
+ }
+ else if (optimized_type == tls::TLSOPT_NONE)
+ {
+ // Relocate the field with the offset of the pair of GOT
+ // entries.
+ value = target->got_plt_section()->address() + got_offset;
+ Relocate_functions<size, false>::pcrela32(view, value, addend,
+ address);
+ break;
+ }
+ }
gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
_("unsupported reloc %u"), r_type);
break;
@@ -3222,16 +3565,16 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
return;
}
this->tls_desc_gd_to_le(relinfo, relnum, tls_segment,
- rela, r_type, value, view,
- view_size);
+ rela, r_type, value, view,
+ view_size);
break;
}
else
- {
- unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
- ? GOT_TYPE_TLS_OFFSET
- : GOT_TYPE_TLS_DESC);
- unsigned int got_offset = 0;
+ {
+ unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
+ ? GOT_TYPE_TLS_OFFSET
+ : GOT_TYPE_TLS_DESC);
+ unsigned int got_offset = 0;
if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC
&& optimized_type == tls::TLSOPT_NONE)
{
@@ -3241,45 +3584,45 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
got_offset = (target->got_size()
+ target->got_plt_section()->data_size());
}
- if (gsym != NULL)
- {
- gold_assert(gsym->has_got_offset(got_type));
- got_offset += gsym->got_offset(got_type) - target->got_size();
- }
- else
- {
- unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym, got_type));
- got_offset += (object->local_got_offset(r_sym, got_type)
+ if (gsym != NULL)
+ {
+ gold_assert(gsym->has_got_offset(got_type));
+ got_offset += gsym->got_offset(got_type) - target->got_size();
+ }
+ else
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+ gold_assert(object->local_has_got_offset(r_sym, got_type));
+ got_offset += (object->local_got_offset(r_sym, got_type)
- target->got_size());
- }
- if (optimized_type == tls::TLSOPT_TO_IE)
- {
+ }
+ if (optimized_type == tls::TLSOPT_TO_IE)
+ {
if (tls_segment == NULL)
{
gold_assert(parameters->errors()->error_count() > 0
|| issue_undefined_symbol_error(gsym));
return;
}
- value = target->got_plt_section()->address() + got_offset;
- this->tls_desc_gd_to_ie(relinfo, relnum, tls_segment,
- rela, r_type, value, view, address,
- view_size);
- break;
- }
- else if (optimized_type == tls::TLSOPT_NONE)
- {
- if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC)
- {
- // Relocate the field with the offset of the pair of GOT
- // entries.
- value = target->got_plt_section()->address() + got_offset;
- Relocate_functions<64, false>::pcrela32(view, value, addend,
- address);
- }
- break;
- }
- }
+ value = target->got_plt_section()->address() + got_offset;
+ this->tls_desc_gd_to_ie(relinfo, relnum, tls_segment,
+ rela, r_type, value, view, address,
+ view_size);
+ break;
+ }
+ else if (optimized_type == tls::TLSOPT_NONE)
+ {
+ if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC)
+ {
+ // Relocate the field with the offset of the pair of GOT
+ // entries.
+ value = target->got_plt_section()->address() + got_offset;
+ Relocate_functions<size, false>::pcrela32(view, value, addend,
+ address);
+ }
+ break;
+ }
+ }
gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
_("unsupported reloc %u"), r_type);
break;
@@ -3291,7 +3634,7 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
optimized_type = tls::TLSOPT_NONE;
}
if (optimized_type == tls::TLSOPT_TO_LE)
- {
+ {
if (tls_segment == NULL)
{
gold_assert(parameters->errors()->error_count() > 0
@@ -3301,19 +3644,19 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
this->tls_ld_to_le(relinfo, relnum, tls_segment, rela, r_type,
value, view, view_size);
break;
- }
+ }
else if (optimized_type == tls::TLSOPT_NONE)
- {
- // Relocate the field with the offset of the GOT entry for
- // the module index.
- unsigned int got_offset;
- got_offset = (target->got_mod_index_entry(NULL, NULL, NULL)
+ {
+ // Relocate the field with the offset of the GOT entry for
+ // the module index.
+ unsigned int got_offset;
+ got_offset = (target->got_mod_index_entry(NULL, NULL, NULL)
- target->got_size());
value = target->got_plt_section()->address() + got_offset;
- Relocate_functions<64, false>::pcrela32(view, value, addend,
- address);
- break;
- }
+ Relocate_functions<size, false>::pcrela32(view, value, addend,
+ address);
+ break;
+ }
gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
_("unsupported reloc %u"), r_type);
break;
@@ -3335,7 +3678,7 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
}
value -= tls_segment->memsz();
}
- Relocate_functions<64, false>::rela32(view, value, addend);
+ Relocate_functions<size, false>::rela32(view, value, addend);
break;
case elfcpp::R_X86_64_DTPOFF64:
@@ -3350,7 +3693,7 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
}
value -= tls_segment->memsz();
}
- Relocate_functions<64, false>::rela64(view, value, addend);
+ Relocate_functions<size, false>::rela64(view, value, addend);
break;
case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec
@@ -3362,34 +3705,36 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
|| issue_undefined_symbol_error(gsym));
return;
}
- Target_x86_64::Relocate::tls_ie_to_le(relinfo, relnum, tls_segment,
- rela, r_type, value, view,
- view_size);
+ Target_x86_64<size>::Relocate::tls_ie_to_le(relinfo, relnum,
+ tls_segment, rela,
+ r_type, value, view,
+ view_size);
break;
}
else if (optimized_type == tls::TLSOPT_NONE)
- {
- // Relocate the field with the offset of the GOT entry for
- // the tp-relative offset of the symbol.
- unsigned int got_offset;
- if (gsym != NULL)
- {
- gold_assert(gsym->has_got_offset(GOT_TYPE_TLS_OFFSET));
- got_offset = (gsym->got_offset(GOT_TYPE_TLS_OFFSET)
- - target->got_size());
- }
- else
- {
- unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
- gold_assert(object->local_has_got_offset(r_sym,
- GOT_TYPE_TLS_OFFSET));
- got_offset = (object->local_got_offset(r_sym, GOT_TYPE_TLS_OFFSET)
- - target->got_size());
- }
+ {
+ // Relocate the field with the offset of the GOT entry for
+ // the tp-relative offset of the symbol.
+ unsigned int got_offset;
+ if (gsym != NULL)
+ {
+ gold_assert(gsym->has_got_offset(GOT_TYPE_TLS_OFFSET));
+ got_offset = (gsym->got_offset(GOT_TYPE_TLS_OFFSET)
+ - target->got_size());
+ }
+ else
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+ gold_assert(object->local_has_got_offset(r_sym,
+ GOT_TYPE_TLS_OFFSET));
+ got_offset = (object->local_got_offset(r_sym, GOT_TYPE_TLS_OFFSET)
+ - target->got_size());
+ }
value = target->got_plt_section()->address() + got_offset;
- Relocate_functions<64, false>::pcrela32(view, value, addend, address);
- break;
- }
+ Relocate_functions<size, false>::pcrela32(view, value, addend,
+ address);
+ break;
+ }
gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
_("unsupported reloc type %u"),
r_type);
@@ -3403,7 +3748,7 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
return;
}
value -= tls_segment->memsz();
- Relocate_functions<64, false>::rela32(view, value, addend);
+ Relocate_functions<size, false>::rela32(view, value, addend);
break;
}
}
@@ -3411,33 +3756,54 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
// Do a relocation in which we convert a TLS General-Dynamic to an
// Initial-Exec.
+template<int size>
inline void
-Target_x86_64::Relocate::tls_gd_to_ie(const Relocate_info<64, false>* relinfo,
- size_t relnum,
- Output_segment*,
- const elfcpp::Rela<64, false>& rela,
- unsigned int,
- elfcpp::Elf_types<64>::Elf_Addr value,
- unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr address,
- section_size_type view_size)
-{
- // .byte 0x66; leaq foo@tlsgd(%rip),%rdi;
- // .word 0x6666; rex64; call __tls_get_addr
- // ==> movq %fs:0,%rax; addq x@gottpoff(%rip),%rax
-
- tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -4);
- tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 12);
+Target_x86_64<size>::Relocate::tls_gd_to_ie(
+ const Relocate_info<size, false>* relinfo,
+ size_t relnum,
+ Output_segment*,
+ const elfcpp::Rela<size, false>& rela,
+ unsigned int,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
+ unsigned char* view,
+ typename elfcpp::Elf_types<size>::Elf_Addr address,
+ section_size_type view_size)
+{
+ // For SIZE == 64:
+ // .byte 0x66; leaq foo@tlsgd(%rip),%rdi;
+ // .word 0x6666; rex64; call __tls_get_addr
+ // ==> movq %fs:0,%rax; addq x@gottpoff(%rip),%rax
+ // For SIZE == 32:
+ // leaq foo@tlsgd(%rip),%rdi;
+ // .word 0x6666; rex64; call __tls_get_addr
+ // ==> movl %fs:0,%eax; addq x@gottpoff(%rip),%rax
+ tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 12);
tls::check_tls(relinfo, relnum, rela.get_r_offset(),
- (memcmp(view - 4, "\x66\x48\x8d\x3d", 4) == 0));
- tls::check_tls(relinfo, relnum, rela.get_r_offset(),
- (memcmp(view + 4, "\x66\x66\x48\xe8", 4) == 0));
+ (memcmp(view + 4, "\x66\x66\x48\xe8", 4) == 0));
- memcpy(view - 4, "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0\0", 16);
+ if (size == 64)
+ {
+ tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size,
+ -4);
+ tls::check_tls(relinfo, relnum, rela.get_r_offset(),
+ (memcmp(view - 4, "\x66\x48\x8d\x3d", 4) == 0));
+ memcpy(view - 4, "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0\0",
+ 16);
+ }
+ else
+ {
+ tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size,
+ -3);
+ tls::check_tls(relinfo, relnum, rela.get_r_offset(),
+ (memcmp(view - 3, "\x48\x8d\x3d", 3) == 0));
+ memcpy(view - 3, "\x64\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0\0",
+ 15);
+ }
const elfcpp::Elf_Xword addend = rela.get_r_addend();
- Relocate_functions<64, false>::pcrela32(view + 8, value, addend - 8, address);
+ Relocate_functions<size, false>::pcrela32(view + 8, value, addend - 8,
+ address);
// The next reloc should be a PLT32 reloc against __tls_get_addr.
// We can skip it.
@@ -3447,32 +3813,53 @@ Target_x86_64::Relocate::tls_gd_to_ie(const Relocate_info<64, false>* relinfo,
// Do a relocation in which we convert a TLS General-Dynamic to a
// Local-Exec.
+template<int size>
inline void
-Target_x86_64::Relocate::tls_gd_to_le(const Relocate_info<64, false>* relinfo,
- size_t relnum,
- Output_segment* tls_segment,
- const elfcpp::Rela<64, false>& rela,
- unsigned int,
- elfcpp::Elf_types<64>::Elf_Addr value,
- unsigned char* view,
- section_size_type view_size)
-{
- // .byte 0x66; leaq foo@tlsgd(%rip),%rdi;
- // .word 0x6666; rex64; call __tls_get_addr
- // ==> movq %fs:0,%rax; leaq x@tpoff(%rax),%rax
-
- tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -4);
- tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 12);
+Target_x86_64<size>::Relocate::tls_gd_to_le(
+ const Relocate_info<size, false>* relinfo,
+ size_t relnum,
+ Output_segment* tls_segment,
+ const elfcpp::Rela<size, false>& rela,
+ unsigned int,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
+ unsigned char* view,
+ section_size_type view_size)
+{
+ // For SIZE == 64:
+ // .byte 0x66; leaq foo@tlsgd(%rip),%rdi;
+ // .word 0x6666; rex64; call __tls_get_addr
+ // ==> movq %fs:0,%rax; leaq x@tpoff(%rax),%rax
+ // For SIZE == 32:
+ // leaq foo@tlsgd(%rip),%rdi;
+ // .word 0x6666; rex64; call __tls_get_addr
+ // ==> movl %fs:0,%eax; leaq x@tpoff(%rax),%rax
+ tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 12);
tls::check_tls(relinfo, relnum, rela.get_r_offset(),
- (memcmp(view - 4, "\x66\x48\x8d\x3d", 4) == 0));
- tls::check_tls(relinfo, relnum, rela.get_r_offset(),
- (memcmp(view + 4, "\x66\x66\x48\xe8", 4) == 0));
+ (memcmp(view + 4, "\x66\x66\x48\xe8", 4) == 0));
+
+ if (size == 64)
+ {
+ tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size,
+ -4);
+ tls::check_tls(relinfo, relnum, rela.get_r_offset(),
+ (memcmp(view - 4, "\x66\x48\x8d\x3d", 4) == 0));
+ memcpy(view - 4, "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0\0",
+ 16);
+ }
+ else
+ {
+ tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size,
+ -3);
+ tls::check_tls(relinfo, relnum, rela.get_r_offset(),
+ (memcmp(view - 3, "\x48\x8d\x3d", 3) == 0));
- memcpy(view - 4, "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0\0", 16);
+ memcpy(view - 3, "\x64\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0\0",
+ 15);
+ }
value -= tls_segment->memsz();
- Relocate_functions<64, false>::rela32(view + 8, value, 0);
+ Relocate_functions<size, false>::rela32(view + 8, value, 0);
// The next reloc should be a PLT32 reloc against __tls_get_addr.
// We can skip it.
@@ -3481,16 +3868,17 @@ Target_x86_64::Relocate::tls_gd_to_le(const Relocate_info<64, false>* relinfo,
// Do a TLSDESC-style General-Dynamic to Initial-Exec transition.
+template<int size>
inline void
-Target_x86_64::Relocate::tls_desc_gd_to_ie(
- const Relocate_info<64, false>* relinfo,
+Target_x86_64<size>::Relocate::tls_desc_gd_to_ie(
+ const Relocate_info<size, false>* relinfo,
size_t relnum,
Output_segment*,
- const elfcpp::Rela<64, false>& rela,
+ const elfcpp::Rela<size, false>& rela,
unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Addr value,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr address,
+ typename elfcpp::Elf_types<size>::Elf_Addr address,
section_size_type view_size)
{
if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC)
@@ -3500,10 +3888,10 @@ Target_x86_64::Relocate::tls_desc_gd_to_ie(
tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -3);
tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 4);
tls::check_tls(relinfo, relnum, rela.get_r_offset(),
- view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x05);
+ view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x05);
view[-2] = 0x8b;
const elfcpp::Elf_Xword addend = rela.get_r_addend();
- Relocate_functions<64, false>::pcrela32(view, value, addend, address);
+ Relocate_functions<size, false>::pcrela32(view, value, addend, address);
}
else
{
@@ -3512,7 +3900,7 @@ Target_x86_64::Relocate::tls_desc_gd_to_ie(
gold_assert(r_type == elfcpp::R_X86_64_TLSDESC_CALL);
tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 2);
tls::check_tls(relinfo, relnum, rela.get_r_offset(),
- view[0] == 0xff && view[1] == 0x10);
+ view[0] == 0xff && view[1] == 0x10);
view[0] = 0x66;
view[1] = 0x90;
}
@@ -3520,14 +3908,15 @@ Target_x86_64::Relocate::tls_desc_gd_to_ie(
// Do a TLSDESC-style General-Dynamic to Local-Exec transition.
+template<int size>
inline void
-Target_x86_64::Relocate::tls_desc_gd_to_le(
- const Relocate_info<64, false>* relinfo,
+Target_x86_64<size>::Relocate::tls_desc_gd_to_le(
+ const Relocate_info<size, false>* relinfo,
size_t relnum,
Output_segment* tls_segment,
- const elfcpp::Rela<64, false>& rela,
+ const elfcpp::Rela<size, false>& rela,
unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Addr value,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned char* view,
section_size_type view_size)
{
@@ -3538,11 +3927,11 @@ Target_x86_64::Relocate::tls_desc_gd_to_le(
tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, -3);
tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 4);
tls::check_tls(relinfo, relnum, rela.get_r_offset(),
- view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x05);
+ view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x05);
view[-2] = 0xc7;
view[-1] = 0xc0;
value -= tls_segment->memsz();
- Relocate_functions<64, false>::rela32(view, value, 0);
+ Relocate_functions<size, false>::rela32(view, value, 0);
}
else
{
@@ -3551,21 +3940,23 @@ Target_x86_64::Relocate::tls_desc_gd_to_le(
gold_assert(r_type == elfcpp::R_X86_64_TLSDESC_CALL);
tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 2);
tls::check_tls(relinfo, relnum, rela.get_r_offset(),
- view[0] == 0xff && view[1] == 0x10);
+ view[0] == 0xff && view[1] == 0x10);
view[0] = 0x66;
view[1] = 0x90;
}
}
+template<int size>
inline void
-Target_x86_64::Relocate::tls_ld_to_le(const Relocate_info<64, false>* relinfo,
- size_t relnum,
- Output_segment*,
- const elfcpp::Rela<64, false>& rela,
- unsigned int,
- elfcpp::Elf_types<64>::Elf_Addr,
- unsigned char* view,
- section_size_type view_size)
+Target_x86_64<size>::Relocate::tls_ld_to_le(
+ const Relocate_info<size, false>* relinfo,
+ size_t relnum,
+ Output_segment*,
+ const elfcpp::Rela<size, false>& rela,
+ unsigned int,
+ typename elfcpp::Elf_types<size>::Elf_Addr,
+ unsigned char* view,
+ section_size_type view_size)
{
// leaq foo@tlsld(%rip),%rdi; call __tls_get_addr@plt;
// ... leq foo@dtpoff(%rax),%reg
@@ -3575,7 +3966,7 @@ Target_x86_64::Relocate::tls_ld_to_le(const Relocate_info<64, false>* relinfo,
tls::check_range(relinfo, relnum, rela.get_r_offset(), view_size, 9);
tls::check_tls(relinfo, relnum, rela.get_r_offset(),
- view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x3d);
+ view[-3] == 0x48 && view[-2] == 0x8d && view[-1] == 0x3d);
tls::check_tls(relinfo, relnum, rela.get_r_offset(), view[4] == 0xe8);
@@ -3589,15 +3980,17 @@ Target_x86_64::Relocate::tls_ld_to_le(const Relocate_info<64, false>* relinfo,
// Do a relocation in which we convert a TLS Initial-Exec to a
// Local-Exec.
+template<int size>
inline void
-Target_x86_64::Relocate::tls_ie_to_le(const Relocate_info<64, false>* relinfo,
- size_t relnum,
- Output_segment* tls_segment,
- const elfcpp::Rela<64, false>& rela,
- unsigned int,
- elfcpp::Elf_types<64>::Elf_Addr value,
- unsigned char* view,
- section_size_type view_size)
+Target_x86_64<size>::Relocate::tls_ie_to_le(
+ const Relocate_info<size, false>* relinfo,
+ size_t relnum,
+ Output_segment* tls_segment,
+ const elfcpp::Rela<size, false>& rela,
+ unsigned int,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
+ unsigned char* view,
+ section_size_type view_size)
{
// We need to examine the opcodes to figure out which instruction we
// are looking at.
@@ -3617,7 +4010,7 @@ Target_x86_64::Relocate::tls_ie_to_le(const Relocate_info<64, false>* relinfo,
{
// movq
if (op1 == 0x4c)
- view[-3] = 0x49;
+ view[-3] = 0x49;
view[-2] = 0xc7;
view[-1] = 0xc0 | reg;
}
@@ -3625,7 +4018,7 @@ Target_x86_64::Relocate::tls_ie_to_le(const Relocate_info<64, false>* relinfo,
{
// Special handling for %rsp.
if (op1 == 0x4c)
- view[-3] = 0x49;
+ view[-3] = 0x49;
view[-2] = 0x81;
view[-1] = 0xc0 | reg;
}
@@ -3633,34 +4026,35 @@ Target_x86_64::Relocate::tls_ie_to_le(const Relocate_info<64, false>* relinfo,
{
// addq
if (op1 == 0x4c)
- view[-3] = 0x4d;
+ view[-3] = 0x4d;
view[-2] = 0x8d;
view[-1] = 0x80 | reg | (reg << 3);
}
value -= tls_segment->memsz();
- Relocate_functions<64, false>::rela32(view, value, 0);
+ Relocate_functions<size, false>::rela32(view, value, 0);
}
// Relocate section data.
+template<int size>
void
-Target_x86_64::relocate_section(
- const Relocate_info<64, false>* relinfo,
+Target_x86_64<size>::relocate_section(
+ const Relocate_info<size, false>* relinfo,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr address,
+ typename elfcpp::Elf_types<size>::Elf_Addr address,
section_size_type view_size,
const Reloc_symbol_changes* reloc_symbol_changes)
{
gold_assert(sh_type == elfcpp::SHT_RELA);
- gold::relocate_section<64, false, Target_x86_64, elfcpp::SHT_RELA,
- Target_x86_64::Relocate>(
+ gold::relocate_section<size, false, Target_x86_64<size>, elfcpp::SHT_RELA,
+ typename Target_x86_64<size>::Relocate>(
relinfo,
this,
prelocs,
@@ -3676,18 +4070,20 @@ Target_x86_64::relocate_section(
// Apply an incremental relocation. Incremental relocations always refer
// to global symbols.
+template<int size>
void
-Target_x86_64::apply_relocation(
- const Relocate_info<64, false>* relinfo,
- elfcpp::Elf_types<64>::Elf_Addr r_offset,
+Target_x86_64<size>::apply_relocation(
+ const Relocate_info<size, false>* relinfo,
+ typename elfcpp::Elf_types<size>::Elf_Addr r_offset,
unsigned int r_type,
- elfcpp::Elf_types<64>::Elf_Swxword r_addend,
+ typename elfcpp::Elf_types<size>::Elf_Swxword r_addend,
const Symbol* gsym,
unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr address,
+ typename elfcpp::Elf_types<size>::Elf_Addr address,
section_size_type view_size)
{
- gold::apply_relocation<64, false, Target_x86_64, Target_x86_64::Relocate>(
+ gold::apply_relocation<size, false, Target_x86_64<size>,
+ typename Target_x86_64<size>::Relocate>(
relinfo,
this,
r_offset,
@@ -3702,8 +4098,9 @@ Target_x86_64::apply_relocation(
// Return the size of a relocation while scanning during a relocatable
// link.
+template<int size>
unsigned int
-Target_x86_64::Relocatable_size_for_reloc::get_size_for_reloc(
+Target_x86_64<size>::Relocatable_size_for_reloc::get_size_for_reloc(
unsigned int r_type,
Relobj* object)
{
@@ -3771,26 +4168,28 @@ Target_x86_64::Relocatable_size_for_reloc::get_size_for_reloc(
// Scan the relocs during a relocatable link.
+template<int size>
void
-Target_x86_64::scan_relocatable_relocs(Symbol_table* symtab,
- Layout* layout,
- Sized_relobj_file<64, false>* object,
- unsigned int data_shndx,
- unsigned int sh_type,
- const unsigned char* prelocs,
- size_t reloc_count,
- Output_section* output_section,
- bool needs_special_offset_handling,
- size_t local_symbol_count,
- const unsigned char* plocal_symbols,
- Relocatable_relocs* rr)
+Target_x86_64<size>::scan_relocatable_relocs(
+ Symbol_table* symtab,
+ Layout* layout,
+ Sized_relobj_file<size, false>* object,
+ unsigned int data_shndx,
+ unsigned int sh_type,
+ const unsigned char* prelocs,
+ size_t reloc_count,
+ Output_section* output_section,
+ bool needs_special_offset_handling,
+ size_t local_symbol_count,
+ const unsigned char* plocal_symbols,
+ Relocatable_relocs* rr)
{
gold_assert(sh_type == elfcpp::SHT_RELA);
typedef gold::Default_scan_relocatable_relocs<elfcpp::SHT_RELA,
Relocatable_size_for_reloc> Scan_relocatable_relocs;
- gold::scan_relocatable_relocs<64, false, elfcpp::SHT_RELA,
+ gold::scan_relocatable_relocs<size, false, elfcpp::SHT_RELA,
Scan_relocatable_relocs>(
symtab,
layout,
@@ -3807,9 +4206,10 @@ Target_x86_64::scan_relocatable_relocs(Symbol_table* symtab,
// Relocate a section during a relocatable link.
+template<int size>
void
-Target_x86_64::relocate_for_relocatable(
- const Relocate_info<64, false>* relinfo,
+Target_x86_64<size>::relocate_for_relocatable(
+ const Relocate_info<size, false>* relinfo,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
@@ -3817,14 +4217,14 @@ Target_x86_64::relocate_for_relocatable(
off_t offset_in_output_section,
const Relocatable_relocs* rr,
unsigned char* view,
- elfcpp::Elf_types<64>::Elf_Addr view_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr view_address,
section_size_type view_size,
unsigned char* reloc_view,
section_size_type reloc_view_size)
{
gold_assert(sh_type == elfcpp::SHT_RELA);
- gold::relocate_for_relocatable<64, false, elfcpp::SHT_RELA>(
+ gold::relocate_for_relocatable<size, false, elfcpp::SHT_RELA>(
relinfo,
prelocs,
reloc_count,
@@ -3843,8 +4243,9 @@ Target_x86_64::relocate_for_relocatable(
// pointers across shared library boundaries, as described in the
// processor specific ABI supplement.
+template<int size>
uint64_t
-Target_x86_64::do_dynsym_value(const Symbol* gsym) const
+Target_x86_64<size>::do_dynsym_value(const Symbol* gsym) const
{
gold_assert(gsym->is_from_dynobj() && gsym->has_plt_offset());
return this->plt_address_for_global(gsym) + gsym->plt_offset();
@@ -3853,8 +4254,9 @@ Target_x86_64::do_dynsym_value(const Symbol* gsym) const
// Return a string used to fill a code section with nops to take up
// the specified length.
+template<int size>
std::string
-Target_x86_64::do_code_fill(section_size_type length) const
+Target_x86_64<size>::do_code_fill(section_size_type length) const
{
if (length >= 16)
{
@@ -3863,7 +4265,7 @@ Target_x86_64::do_code_fill(section_size_type length) const
jmp[0] = 0xe9;
elfcpp::Swap_unaligned<32, false>::writeval(jmp + 1, length - 5);
return (std::string(reinterpret_cast<char*>(&jmp[0]), 5)
- + std::string(length - 5, '\0'));
+ + std::string(length - 5, static_cast<char>(0x90)));
}
// Nop sequences of various lengths.
@@ -3871,47 +4273,47 @@ Target_x86_64::do_code_fill(section_size_type length) const
const char nop2[2] = { '\x66', '\x90' }; // xchg %ax %ax
const char nop3[3] = { '\x0f', '\x1f', '\x00' }; // nop (%rax)
const char nop4[4] = { '\x0f', '\x1f', '\x40', // nop 0(%rax)
- '\x00'};
+ '\x00'};
const char nop5[5] = { '\x0f', '\x1f', '\x44', // nop 0(%rax,%rax,1)
'\x00', '\x00' };
const char nop6[6] = { '\x66', '\x0f', '\x1f', // nopw 0(%rax,%rax,1)
- '\x44', '\x00', '\x00' };
+ '\x44', '\x00', '\x00' };
const char nop7[7] = { '\x0f', '\x1f', '\x80', // nopl 0L(%rax)
- '\x00', '\x00', '\x00',
+ '\x00', '\x00', '\x00',
'\x00' };
const char nop8[8] = { '\x0f', '\x1f', '\x84', // nopl 0L(%rax,%rax,1)
- '\x00', '\x00', '\x00',
+ '\x00', '\x00', '\x00',
'\x00', '\x00' };
const char nop9[9] = { '\x66', '\x0f', '\x1f', // nopw 0L(%rax,%rax,1)
- '\x84', '\x00', '\x00',
+ '\x84', '\x00', '\x00',
'\x00', '\x00', '\x00' };
const char nop10[10] = { '\x66', '\x2e', '\x0f', // nopw %cs:0L(%rax,%rax,1)
- '\x1f', '\x84', '\x00',
+ '\x1f', '\x84', '\x00',
'\x00', '\x00', '\x00',
'\x00' };
const char nop11[11] = { '\x66', '\x66', '\x2e', // data16
- '\x0f', '\x1f', '\x84', // nopw %cs:0L(%rax,%rax,1)
+ '\x0f', '\x1f', '\x84', // nopw %cs:0L(%rax,%rax,1)
'\x00', '\x00', '\x00',
'\x00', '\x00' };
const char nop12[12] = { '\x66', '\x66', '\x66', // data16; data16
- '\x2e', '\x0f', '\x1f', // nopw %cs:0L(%rax,%rax,1)
+ '\x2e', '\x0f', '\x1f', // nopw %cs:0L(%rax,%rax,1)
'\x84', '\x00', '\x00',
'\x00', '\x00', '\x00' };
const char nop13[13] = { '\x66', '\x66', '\x66', // data16; data16; data16
- '\x66', '\x2e', '\x0f', // nopw %cs:0L(%rax,%rax,1)
+ '\x66', '\x2e', '\x0f', // nopw %cs:0L(%rax,%rax,1)
'\x1f', '\x84', '\x00',
'\x00', '\x00', '\x00',
- '\x00' };
+ '\x00' };
const char nop14[14] = { '\x66', '\x66', '\x66', // data16; data16; data16
- '\x66', '\x66', '\x2e', // data16
+ '\x66', '\x66', '\x2e', // data16
'\x0f', '\x1f', '\x84', // nopw %cs:0L(%rax,%rax,1)
'\x00', '\x00', '\x00',
- '\x00', '\x00' };
+ '\x00', '\x00' };
const char nop15[15] = { '\x66', '\x66', '\x66', // data16; data16; data16
- '\x66', '\x66', '\x66', // data16; data16
+ '\x66', '\x66', '\x66', // data16; data16
'\x2e', '\x0f', '\x1f', // nopw %cs:0L(%rax,%rax,1)
'\x84', '\x00', '\x00',
- '\x00', '\x00', '\x00' };
+ '\x00', '\x00', '\x00' };
const char* nops[16] = {
NULL,
@@ -3927,15 +4329,16 @@ Target_x86_64::do_code_fill(section_size_type length) const
// symbol. We want to set the addend is the offset of the local
// symbol in the TLS segment.
+template<int size>
uint64_t
-Target_x86_64::do_reloc_addend(void* arg, unsigned int r_type,
- uint64_t) const
+Target_x86_64<size>::do_reloc_addend(void* arg, unsigned int r_type,
+ uint64_t) const
{
gold_assert(r_type == elfcpp::R_X86_64_TLSDESC);
uintptr_t intarg = reinterpret_cast<uintptr_t>(arg);
gold_assert(intarg < this->tlsdesc_reloc_info_.size());
const Tlsdesc_info& ti(this->tlsdesc_reloc_info_[intarg]);
- const Symbol_value<64>* psymval = ti.object->local_symbol(ti.r_sym);
+ const Symbol_value<size>* psymval = ti.object->local_symbol(ti.r_sym);
gold_assert(psymval->is_tls_symbol());
// The value of a TLS symbol is the offset in the TLS segment.
return psymval->value(ti.object, 0);
@@ -3947,12 +4350,13 @@ Target_x86_64::do_reloc_addend(void* arg, unsigned int r_type,
// different sections, so instead of using a pc-relative value they
// use an offset from the GOT.
+template<int size>
uint64_t
-Target_x86_64::do_ehframe_datarel_base() const
+Target_x86_64<size>::do_ehframe_datarel_base() const
{
gold_assert(this->global_offset_table_ != NULL);
Symbol* sym = this->global_offset_table_;
- Sized_symbol<64>* ssym = static_cast<Sized_symbol<64>*>(sym);
+ Sized_symbol<size>* ssym = static_cast<Sized_symbol<size>*>(sym);
return ssym->value();
}
@@ -3961,14 +4365,15 @@ Target_x86_64::do_ehframe_datarel_base() const
// code. We have to change the function so that it always ensures
// that it has enough stack space to run some random function.
+template<int size>
void
-Target_x86_64::do_calls_non_split(Relobj* object, unsigned int shndx,
- section_offset_type fnoffset,
- section_size_type fnsize,
- unsigned char* view,
- section_size_type view_size,
- std::string* from,
- std::string* to) const
+Target_x86_64<size>::do_calls_non_split(Relobj* object, unsigned int shndx,
+ section_offset_type fnoffset,
+ section_size_type fnsize,
+ unsigned char* view,
+ section_size_type view_size,
+ std::string* from,
+ std::string* to) const
{
// The function starts with a comparison of the stack pointer and a
// field in the TCB. This is followed by a jump.
@@ -4017,22 +4422,382 @@ Target_x86_64::do_calls_non_split(Relobj* object, unsigned int shndx,
*to = "__morestack_non_split";
}
-// The selector for x86_64 object files.
+// The selector for x86_64 object files. Note this is never instantiated
+// directly. It's only used in Target_selector_x86_64_nacl, below.
+template<int size>
class Target_selector_x86_64 : public Target_selector_freebsd
{
public:
Target_selector_x86_64()
- : Target_selector_freebsd(elfcpp::EM_X86_64, 64, false, "elf64-x86-64",
- "elf64-x86-64-freebsd", "elf_x86_64")
+ : Target_selector_freebsd(elfcpp::EM_X86_64, size, false,
+ (size == 64
+ ? "elf64-x86-64" : "elf32-x86-64"),
+ (size == 64
+ ? "elf64-x86-64-freebsd"
+ : "elf32-x86-64-freebsd"),
+ (size == 64 ? "elf_x86_64" : "elf32_x86_64"))
{ }
Target*
do_instantiate_target()
- { return new Target_x86_64(); }
+ { return new Target_x86_64<size>(); }
+
+};
+
+// NaCl variant. It uses different PLT contents.
+
+template<int size>
+class Output_data_plt_x86_64_nacl : public Output_data_plt_x86_64<size>
+{
+ public:
+ Output_data_plt_x86_64_nacl(Layout* layout,
+ Output_data_got<64, false>* got,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative)
+ : Output_data_plt_x86_64<size>(layout, plt_entry_size,
+ got, got_plt, got_irelative)
+ { }
+
+ Output_data_plt_x86_64_nacl(Layout* layout,
+ Output_data_got<64, false>* got,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative,
+ unsigned int plt_count)
+ : Output_data_plt_x86_64<size>(layout, plt_entry_size,
+ got, got_plt, got_irelative,
+ plt_count)
+ { }
+
+ protected:
+ virtual unsigned int
+ do_get_plt_entry_size() const
+ { return plt_entry_size; }
+
+ virtual void
+ do_add_eh_frame(Layout* layout)
+ {
+ layout->add_eh_frame_for_plt(this,
+ this->plt_eh_frame_cie,
+ this->plt_eh_frame_cie_size,
+ plt_eh_frame_fde,
+ plt_eh_frame_fde_size);
+ }
+
+ virtual void
+ do_fill_first_plt_entry(unsigned char* pov,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_addr,
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_addr);
+
+ virtual unsigned int
+ do_fill_plt_entry(unsigned char* pov,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+ unsigned int got_offset,
+ unsigned int plt_offset,
+ unsigned int plt_index);
+
+ virtual void
+ do_fill_tlsdesc_entry(unsigned char* pov,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_base,
+ unsigned int tlsdesc_got_offset,
+ unsigned int plt_offset);
+
+ private:
+ // The size of an entry in the PLT.
+ static const int plt_entry_size = 64;
+
+ // The first entry in the PLT.
+ static const unsigned char first_plt_entry[plt_entry_size];
+
+ // Other entries in the PLT for an executable.
+ static const unsigned char plt_entry[plt_entry_size];
+
+ // The reserved TLSDESC entry in the PLT for an executable.
+ static const unsigned char tlsdesc_plt_entry[plt_entry_size];
+
+ // The .eh_frame unwind information for the PLT.
+ static const int plt_eh_frame_fde_size = 32;
+ static const unsigned char plt_eh_frame_fde[plt_eh_frame_fde_size];
+};
+
+template<int size>
+class Target_x86_64_nacl : public Target_x86_64<size>
+{
+ public:
+ Target_x86_64_nacl()
+ : Target_x86_64<size>(&x86_64_nacl_info)
+ { }
+
+ virtual Output_data_plt_x86_64<size>*
+ do_make_data_plt(Layout* layout,
+ Output_data_got<64, false>* got,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative)
+ {
+ return new Output_data_plt_x86_64_nacl<size>(layout, got, got_plt,
+ got_irelative);
+ }
+
+ virtual Output_data_plt_x86_64<size>*
+ do_make_data_plt(Layout* layout,
+ Output_data_got<64, false>* got,
+ Output_data_space* got_plt,
+ Output_data_space* got_irelative,
+ unsigned int plt_count)
+ {
+ return new Output_data_plt_x86_64_nacl<size>(layout, got, got_plt,
+ got_irelative,
+ plt_count);
+ }
+
+ private:
+ static const Target::Target_info x86_64_nacl_info;
+};
+
+template<>
+const Target::Target_info Target_x86_64_nacl<64>::x86_64_nacl_info =
+{
+ 64, // size
+ false, // is_big_endian
+ elfcpp::EM_X86_64, // machine_code
+ false, // has_make_symbol
+ false, // has_resolve
+ true, // has_code_fill
+ true, // is_default_stack_executable
+ true, // can_icf_inline_merge_sections
+ '\0', // wrap_char
+ "/lib64/ld-nacl-x86-64.so.1", // dynamic_linker
+ 0x20000, // default_text_segment_address
+ 0x10000, // abi_pagesize (overridable by -z max-page-size)
+ 0x10000, // common_pagesize (overridable by -z common-page-size)
+ true, // isolate_execinstr
+ 0x10000000, // rosegment_gap
+ elfcpp::SHN_UNDEF, // small_common_shndx
+ elfcpp::SHN_X86_64_LCOMMON, // large_common_shndx
+ 0, // small_common_section_flags
+ elfcpp::SHF_X86_64_LARGE, // large_common_section_flags
+ NULL, // attributes_section
+ NULL // attributes_vendor
+};
+template<>
+const Target::Target_info Target_x86_64_nacl<32>::x86_64_nacl_info =
+{
+ 32, // size
+ false, // is_big_endian
+ elfcpp::EM_X86_64, // machine_code
+ false, // has_make_symbol
+ false, // has_resolve
+ true, // has_code_fill
+ true, // is_default_stack_executable
+ true, // can_icf_inline_merge_sections
+ '\0', // wrap_char
+ "/lib/ld-nacl-x86-64.so.1", // dynamic_linker
+ 0x20000, // default_text_segment_address
+ 0x10000, // abi_pagesize (overridable by -z max-page-size)
+ 0x10000, // common_pagesize (overridable by -z common-page-size)
+ true, // isolate_execinstr
+ 0x10000000, // rosegment_gap
+ elfcpp::SHN_UNDEF, // small_common_shndx
+ elfcpp::SHN_X86_64_LCOMMON, // large_common_shndx
+ 0, // small_common_section_flags
+ elfcpp::SHF_X86_64_LARGE, // large_common_section_flags
+ NULL, // attributes_section
+ NULL // attributes_vendor
+};
+
+#define NACLMASK 0xe0 // 32-byte alignment mask.
+
+// The first entry in the PLT.
+
+template<int size>
+const unsigned char
+Output_data_plt_x86_64_nacl<size>::first_plt_entry[plt_entry_size] =
+{
+ 0xff, 0x35, // pushq contents of memory address
+ 0, 0, 0, 0, // replaced with address of .got + 8
+ 0x4c, 0x8b, 0x1d, // mov GOT+16(%rip), %r11
+ 0, 0, 0, 0, // replaced with address of .got + 16
+ 0x41, 0x83, 0xe3, NACLMASK, // and $-32, %r11d
+ 0x4d, 0x01, 0xfb, // add %r15, %r11
+ 0x41, 0xff, 0xe3, // jmpq *%r11
+
+ // 9-byte nop sequence to pad out to the next 32-byte boundary.
+ 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopl %cs:0x0(%rax,%rax,1)
+
+ // 32 bytes of nop to pad out to the standard size
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, // excess data32 prefixes
+ 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1)
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, // excess data32 prefixes
+ 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1)
+ 0x66, // excess data32 prefix
+ 0x90 // nop
+};
+
+template<int size>
+void
+Output_data_plt_x86_64_nacl<size>::do_fill_first_plt_entry(
+ unsigned char* pov,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_address)
+{
+ memcpy(pov, first_plt_entry, plt_entry_size);
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
+ (got_address + 8
+ - (plt_address + 2 + 4)));
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 9,
+ (got_address + 16
+ - (plt_address + 9 + 4)));
+}
+
+// Subsequent entries in the PLT.
+
+template<int size>
+const unsigned char
+Output_data_plt_x86_64_nacl<size>::plt_entry[plt_entry_size] =
+{
+ 0x4c, 0x8b, 0x1d, // mov name@GOTPCREL(%rip),%r11
+ 0, 0, 0, 0, // replaced with address of symbol in .got
+ 0x41, 0x83, 0xe3, NACLMASK, // and $-32, %r11d
+ 0x4d, 0x01, 0xfb, // add %r15, %r11
+ 0x41, 0xff, 0xe3, // jmpq *%r11
+
+ // 15-byte nop sequence to pad out to the next 32-byte boundary.
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, // excess data32 prefixes
+ 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1)
+
+ // Lazy GOT entries point here (32-byte aligned).
+ 0x68, // pushq immediate
+ 0, 0, 0, 0, // replaced with index into relocation table
+ 0xe9, // jmp relative
+ 0, 0, 0, 0, // replaced with offset to start of .plt0
+
+ // 22 bytes of nop to pad out to the standard size.
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, // excess data32 prefixes
+ 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1)
+ 0x0f, 0x1f, 0x80, 0, 0, 0, 0, // nopl 0x0(%rax)
+};
+
+template<int size>
+unsigned int
+Output_data_plt_x86_64_nacl<size>::do_fill_plt_entry(
+ unsigned char* pov,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+ unsigned int got_offset,
+ unsigned int plt_offset,
+ unsigned int plt_index)
+{
+ memcpy(pov, plt_entry, plt_entry_size);
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 3,
+ (got_address + got_offset
+ - (plt_address + plt_offset
+ + 3 + 4)));
+
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 33, plt_index);
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 38,
+ - (plt_offset + 38 + 4));
+
+ return 32;
+}
+
+// The reserved TLSDESC entry in the PLT.
+
+template<int size>
+const unsigned char
+Output_data_plt_x86_64_nacl<size>::tlsdesc_plt_entry[plt_entry_size] =
+{
+ 0xff, 0x35, // pushq x(%rip)
+ 0, 0, 0, 0, // replaced with address of linkmap GOT entry (at PLTGOT + 8)
+ 0x4c, 0x8b, 0x1d, // mov y(%rip),%r11
+ 0, 0, 0, 0, // replaced with offset of reserved TLSDESC_GOT entry
+ 0x41, 0x83, 0xe3, NACLMASK, // and $-32, %r11d
+ 0x4d, 0x01, 0xfb, // add %r15, %r11
+ 0x41, 0xff, 0xe3, // jmpq *%r11
+
+ // 41 bytes of nop to pad out to the standard size.
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, // excess data32 prefixes
+ 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1)
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, // excess data32 prefixes
+ 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1)
+ 0x66, 0x66, // excess data32 prefixes
+ 0x2e, 0x0f, 0x1f, 0x84, 0, 0, 0, 0, 0, // nopw %cs:0x0(%rax,%rax,1)
+};
+
+template<int size>
+void
+Output_data_plt_x86_64_nacl<size>::do_fill_tlsdesc_entry(
+ unsigned char* pov,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr plt_address,
+ typename elfcpp::Elf_types<size>::Elf_Addr got_base,
+ unsigned int tlsdesc_got_offset,
+ unsigned int plt_offset)
+{
+ memcpy(pov, tlsdesc_plt_entry, plt_entry_size);
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
+ (got_address + 8
+ - (plt_address + plt_offset
+ + 2 + 4)));
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 9,
+ (got_base
+ + tlsdesc_got_offset
+ - (plt_address + plt_offset
+ + 9 + 4)));
+}
+
+// The .eh_frame unwind information for the PLT.
+
+template<int size>
+const unsigned char
+Output_data_plt_x86_64_nacl<size>::plt_eh_frame_fde[plt_eh_frame_fde_size] =
+{
+ 0, 0, 0, 0, // Replaced with offset to .plt.
+ 0, 0, 0, 0, // Replaced with size of .plt.
+ 0, // Augmentation size.
+ elfcpp::DW_CFA_def_cfa_offset, 16, // DW_CFA_def_cfa_offset: 16.
+ elfcpp::DW_CFA_advance_loc + 6, // Advance 6 to __PLT__ + 6.
+ elfcpp::DW_CFA_def_cfa_offset, 24, // DW_CFA_def_cfa_offset: 24.
+ elfcpp::DW_CFA_advance_loc + 58, // Advance 58 to __PLT__ + 64.
+ elfcpp::DW_CFA_def_cfa_expression, // DW_CFA_def_cfa_expression.
+ 13, // Block length.
+ elfcpp::DW_OP_breg7, 8, // Push %rsp + 8.
+ elfcpp::DW_OP_breg16, 0, // Push %rip.
+ elfcpp::DW_OP_const1u, 63, // Push 0x3f.
+ elfcpp::DW_OP_and, // & (%rip & 0x3f).
+ elfcpp::DW_OP_const1u, 37, // Push 0x25.
+ elfcpp::DW_OP_ge, // >= ((%rip & 0x3f) >= 0x25)
+ elfcpp::DW_OP_lit3, // Push 3.
+ elfcpp::DW_OP_shl, // << (((%rip & 0x3f) >= 0x25) << 3)
+ elfcpp::DW_OP_plus, // + ((((%rip&0x3f)>=0x25)<<3)+%rsp+8
+ elfcpp::DW_CFA_nop, // Align to 32 bytes.
+ elfcpp::DW_CFA_nop
+};
+
+// The selector for x86_64-nacl object files.
+
+template<int size>
+class Target_selector_x86_64_nacl
+ : public Target_selector_nacl<Target_selector_x86_64<size>,
+ Target_x86_64_nacl<size> >
+{
+ public:
+ Target_selector_x86_64_nacl()
+ : Target_selector_nacl<Target_selector_x86_64<size>,
+ Target_x86_64_nacl<size> >("x86-64",
+ size == 64
+ ? "elf64-x86-64-nacl"
+ : "elf32-x86-64-nacl",
+ size == 64
+ ? "elf_x86_64_nacl"
+ : "elf32_x86_64_nacl")
+ { }
};
-Target_selector_x86_64 target_selector_x86_64;
+Target_selector_x86_64_nacl<64> target_selector_x86_64;
+Target_selector_x86_64_nacl<32> target_selector_x32;
} // End anonymous namespace.
diff --git a/binutils-2.22/gold/yyscript.y b/binutils-2.22/gold/yyscript.y
index 18f9496..51c755b 100644
--- a/binutils-2.22/gold/yyscript.y
+++ b/binutils-2.22/gold/yyscript.y
@@ -528,6 +528,8 @@ section_cmd:
nothing, we accept it and ignore it. */
}
| SORT_BY_NAME '(' CONSTRUCTORS ')'
+ | INCLUDE string
+ { script_include_directive(closure, $2.value, $2.length); }
| ';'
;
@@ -689,6 +691,8 @@ file_or_sections_cmd:
| assignment end
| ASSERT_K '(' parse_exp ',' string ')'
{ script_add_assertion(closure, $3, $5.value, $5.length); }
+ | INCLUDE string
+ { script_include_directive(closure, $2.value, $2.length); }
;
/* A list of MEMORY definitions. */