* 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.
This commit is contained in:
parent
6b467df6a5
commit
d8f5a2749d
4 changed files with 103 additions and 5 deletions
|
@ -1,3 +1,16 @@
|
|||
2012-12-12 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* 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 <mcgrathr@google.com>
|
||||
|
||||
* testsuite/binary_unittest.cc (read_all): New function.
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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*
|
||||
|
|
|
@ -71,7 +71,7 @@ public:
|
|||
Powerpc_relobj(const std::string& name, Input_file* input_file, off_t offset,
|
||||
const typename elfcpp::Ehdr<size, big_endian>& ehdr)
|
||||
: Sized_relobj_file<size, big_endian>(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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::define_save_restore_funcs(
|
|||
}
|
||||
}
|
||||
|
||||
// Sort linker created .got section first (for the header), then input
|
||||
// sections belonging to files using small model code.
|
||||
|
||||
template<bool big_endian>
|
||||
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<const Powerpc_relobj<64, big_endian>*>(is1.relobj())
|
||||
->has_small_toc_reloc()));
|
||||
bool small2
|
||||
= (is2.is_input_section()
|
||||
&& (static_cast<const Powerpc_relobj<64, big_endian>*>(is2.relobj())
|
||||
->has_small_toc_reloc()));
|
||||
return small1 && !small2;
|
||||
}
|
||||
};
|
||||
|
||||
// Finalize the sections.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
|
@ -5399,6 +5466,15 @@ Target_powerpc<size, big_endian>::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<big_endian>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6063,7 +6139,7 @@ Target_powerpc<size, big_endian>::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<Insn*>(view - 2 * big_endian);
|
||||
Insn insn = elfcpp::Swap<32, big_endian>::readval(iview);
|
||||
|
@ -6088,7 +6164,7 @@ Target_powerpc<size, big_endian>::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<Insn*>(view - 2 * big_endian);
|
||||
Insn insn = elfcpp::Swap<32, big_endian>::readval(iview);
|
||||
|
|
Loading…
Reference in a new issue