From: Alan Modra Date: Wed, 12 Dec 2012 03:41:40 +0000 (+0000) Subject: * options.h (General_options): Add --toc-sort/--no-toc-sort. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d8f5a2749d0409237cb681bb47c4a625c410f238;p=binutils-gdb.git * options.h (General_options): Add --toc-sort/--no-toc-sort. Replace no_toc_optimize with toc_optimize. * output.h (Output_section::input_sections): Provide non-const variant. * powerpc.cc (Powerpc_relobj::has_small_toc_reloc_, set_has_small_toc_reloc, has_small_toc_reloc): New variable and accessors. (Target_powerpc::Scan::local, global): Call set_has_small_toc_reloc. (class Sort_toc_sections): New. (Target_powerpc::do_finalize_sections): Sort toc sections. (Target_powerpc::Relocate::relocate): Update toc_optimize test. --- diff --git a/gold/ChangeLog b/gold/ChangeLog index d11160af5be..fb0d734df7d 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,16 @@ +2012-12-12 Alan Modra + + * options.h (General_options): Add --toc-sort/--no-toc-sort. + Replace no_toc_optimize with toc_optimize. + * output.h (Output_section::input_sections): Provide non-const variant. + * powerpc.cc (Powerpc_relobj::has_small_toc_reloc_, + set_has_small_toc_reloc, has_small_toc_reloc): New variable and + accessors. + (Target_powerpc::Scan::local, global): Call set_has_small_toc_reloc. + (class Sort_toc_sections): New. + (Target_powerpc::do_finalize_sections): Sort toc sections. + (Target_powerpc::Relocate::relocate): Update toc_optimize test. + 2012-12-10 Roland McGrath * testsuite/binary_unittest.cc (read_all): New function. diff --git a/gold/options.h b/gold/options.h index 1a25b7b070d..38f0c00ad26 100644 --- a/gold/options.h +++ b/gold/options.h @@ -1109,8 +1109,13 @@ class General_options DEFINE_uint64(Ttext, options::ONE_DASH, '\0', -1U, N_("Set the address of the text segment"), N_("ADDRESS")); - DEFINE_bool(no_toc_optimize, options::TWO_DASHES, '\0', false, - N_("(PowerPC64 only) Don't optimize TOC code sequences"), NULL); + DEFINE_bool(toc_optimize, options::TWO_DASHES, '\0', true, + N_("(PowerPC64 only) Optimize TOC code sequences"), + N_("(PowerPC64 only) Don't optimize TOC code sequences")); + + DEFINE_bool(toc_sort, options::TWO_DASHES, '\0', true, + N_("(PowerPC64 only) Sort TOC and GOT sections"), + N_("(PowerPC64 only) Don't sort TOC and GOT sections")); DEFINE_set(undefined, options::TWO_DASHES, 'u', N_("Create undefined reference to SYMBOL"), N_("SYMBOL")); diff --git a/gold/output.h b/gold/output.h index bd108bbd418..a8fe59405b9 100644 --- a/gold/output.h +++ b/gold/output.h @@ -3941,6 +3941,10 @@ class Output_section : public Output_data input_sections() const { return this->input_sections_; } + Input_section_list& + input_sections() + { return this->input_sections_; } + protected: // Return the output section--i.e., the object itself. Output_section* diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 32b7b70b8aa..edd48e707d9 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -71,7 +71,7 @@ public: Powerpc_relobj(const std::string& name, Input_file* input_file, off_t offset, const typename elfcpp::Ehdr& ehdr) : Sized_relobj_file(name, input_file, offset, ehdr), - special_(0), opd_valid_(false), + special_(0), has_small_toc_reloc_(false), opd_valid_(false), opd_ent_(), access_from_map_(), has14_(), stub_table_() { } @@ -227,6 +227,14 @@ public: toc_base_offset() const { return 0x8000; } + void + set_has_small_toc_reloc() + { has_small_toc_reloc_ = true; } + + bool + has_small_toc_reloc() const + { return has_small_toc_reloc_; } + void set_has_14bit_branch(unsigned int shndx) { @@ -281,6 +289,10 @@ private: // For 32-bit the .got2 section shdnx, for 64-bit the .opd section shndx. unsigned int special_; + // For 64-bit, whether this object uses small model relocs to access + // the toc. + bool has_small_toc_reloc_; + // Set at the start of gc_process_relocs, when we know opd_ent_ // vector is valid. The flag could be made atomic and set in // do_read_relocs with memory_order_release and then tested with @@ -4690,6 +4702,21 @@ Target_powerpc::Scan::local( unsupported_reloc_local(object, r_type); break; } + + switch (r_type) + { + case elfcpp::R_POWERPC_GOT_TLSLD16: + case elfcpp::R_POWERPC_GOT_TLSGD16: + case elfcpp::R_POWERPC_GOT_TPREL16: + case elfcpp::R_POWERPC_GOT_DTPREL16: + case elfcpp::R_POWERPC_GOT16: + case elfcpp::R_PPC64_GOT16_DS: + case elfcpp::R_PPC64_TOC16: + case elfcpp::R_PPC64_TOC16_DS: + ppc_object->set_has_small_toc_reloc(); + default: + break; + } } // Report an unsupported relocation against a global symbol. @@ -5126,6 +5153,21 @@ Target_powerpc::Scan::global( unsupported_reloc_global(object, r_type, gsym); break; } + + switch (r_type) + { + case elfcpp::R_POWERPC_GOT_TLSLD16: + case elfcpp::R_POWERPC_GOT_TLSGD16: + case elfcpp::R_POWERPC_GOT_TPREL16: + case elfcpp::R_POWERPC_GOT_DTPREL16: + case elfcpp::R_POWERPC_GOT16: + case elfcpp::R_PPC64_GOT16_DS: + case elfcpp::R_PPC64_TOC16: + case elfcpp::R_PPC64_TOC16_DS: + ppc_object->set_has_small_toc_reloc(); + default: + break; + } } // Process relocations for gc. @@ -5346,6 +5388,31 @@ Target_powerpc::define_save_restore_funcs( } } +// Sort linker created .got section first (for the header), then input +// sections belonging to files using small model code. + +template +class Sort_toc_sections +{ + public: + bool + operator()(const Output_section::Input_section& is1, + const Output_section::Input_section& is2) const + { + if (!is1.is_input_section() && is2.is_input_section()) + return true; + bool small1 + = (is1.is_input_section() + && (static_cast*>(is1.relobj()) + ->has_small_toc_reloc())); + bool small2 + = (is2.is_input_section() + && (static_cast*>(is2.relobj()) + ->has_small_toc_reloc())); + return small1 && !small2; + } +}; + // Finalize the sections. template @@ -5399,6 +5466,15 @@ Target_powerpc::do_finalize_sections( // need to mess with the relaxation machinery checkpointing. this->got_section(symtab, layout); this->make_brlt_section(layout); + + if (parameters->options().toc_sort()) + { + Output_section* os = this->got_->output_section(); + if (os != NULL && os->input_sections().size() > 1) + std::stable_sort(os->input_sections().begin(), + os->input_sections().end(), + Sort_toc_sections()); + } } } @@ -6063,7 +6139,7 @@ Target_powerpc::Relocate::relocate( case elfcpp::R_POWERPC_GOT_DTPREL16_HA: case elfcpp::R_POWERPC_GOT16_HA: case elfcpp::R_PPC64_TOC16_HA: - if (!parameters->options().no_toc_optimize()) + if (parameters->options().toc_optimize()) { Insn* iview = reinterpret_cast(view - 2 * big_endian); Insn insn = elfcpp::Swap<32, big_endian>::readval(iview); @@ -6088,7 +6164,7 @@ Target_powerpc::Relocate::relocate( case elfcpp::R_PPC64_GOT16_LO_DS: case elfcpp::R_PPC64_TOC16_LO: case elfcpp::R_PPC64_TOC16_LO_DS: - if (!parameters->options().no_toc_optimize()) + if (parameters->options().toc_optimize()) { Insn* iview = reinterpret_cast(view - 2 * big_endian); Insn insn = elfcpp::Swap<32, big_endian>::readval(iview);