diff options
Diffstat (limited to 'binutils-2.22/gold')
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, §ion_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*>(¶meters->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(¶meters->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(¶meters->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 Binary files differindex e79c304..27b0753 100644 --- a/binutils-2.22/gold/po/es.gmo +++ b/binutils-2.22/gold/po/es.gmo 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 Binary files differindex 59175d3..8e5149d 100644 --- a/binutils-2.22/gold/po/fi.gmo +++ b/binutils-2.22/gold/po/fi.gmo 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 Binary files differnew file mode 100644 index 0000000..b79d83a --- /dev/null +++ b/binutils-2.22/gold/po/it.gmo 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, - §ion, NULL); + §ion, 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. */ |