* layout.h (Layout::get_executable_sections): Declare.
* layout.cc (Layout::get_executable_sections): New function. * arm.cc (Target_arm::group_sections): Use it. (Arm_output_section::group_sections): Delete now redundant test. * output.cc (Output_reloc::Output_reloc): Add is_relative. param to handle relative relocs. * output.h (Output_reloc::Output_reloc <absolute reloc>): Likewise. (Output_data_reloc::add_absolute): Adjust. (Output_data_reloc::add_relative): New function. (Output_data::reset_data_size): New function. (Output_relaxed_input_section::set_relobj, set_shndx): New functions. (Output_section::set_addralign): New function. (Output_section::checkpoint_set_addralign): New function. (Output_section::clear_section_offsets_need_adjustment): New function. (Output_section::input_sections): Make public. * powerpc.cc (class Output_data_brlt_powerpc): New. (class Stub_table, class Stub_control): New. (Powerpc_relobj::has14_, set_has_14bit_branch, has_14bit_branch, stub_table_, set_stub_table, stub_table): New vectors and accessor functions. (Target_powerpc::do_may_relax, do_relax, push_branch, new_stub_table, stub_tables, brlt_section, group_sections, add_branch_lookup_table, find_branch_lookup_table, write_branch_lookup_table, make_brlt_section): New functions. (Target_powerpc::struct Sort_sections, class Branch_info): New. (Target_powerpc::brlt_section_, stub_tables_, branch_lookup_table_, branch_info_): New vars. (Target_powerpc::make_plt_entry, make_local_ifunc_plt_entry): Don't make call stubs here. (Output_data_glink): Remove all call stub handling from this class. (Target_powerpc::Scan::local, global): Save interesting branch relocs and relocs for ifunc. Adjust calls to plt entry functions. (Target_powerpc::do_finalize_sections): Only make reg save/restore functions on final link. (Target_powerpc::Relocate::relocate): Adjust lookup of call stubs. Handle long branch destinations too. (Target_powerpc::do_dynsym_value, do_plt_address_for_global, do_plt_address_for_local): Adjust lookup of plt call stubs.
This commit is contained in:
parent
0f6752b51f
commit
ec661b9dca
7 changed files with 1680 additions and 477 deletions
|
@ -1,3 +1,44 @@
|
||||||
|
i2012-12-03 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* layout.h (Layout::get_executable_sections): Declare.
|
||||||
|
* layout.cc (Layout::get_executable_sections): New function.
|
||||||
|
* arm.cc (Target_arm::group_sections): Use it.
|
||||||
|
(Arm_output_section::group_sections): Delete now redundant test.
|
||||||
|
* output.cc (Output_reloc::Output_reloc): Add is_relative.
|
||||||
|
param to handle relative relocs.
|
||||||
|
* output.h (Output_reloc::Output_reloc <absolute reloc>): Likewise.
|
||||||
|
(Output_data_reloc::add_absolute): Adjust.
|
||||||
|
(Output_data_reloc::add_relative): New function.
|
||||||
|
(Output_data::reset_data_size): New function.
|
||||||
|
(Output_relaxed_input_section::set_relobj, set_shndx): New functions.
|
||||||
|
(Output_section::set_addralign): New function.
|
||||||
|
(Output_section::checkpoint_set_addralign): New function.
|
||||||
|
(Output_section::clear_section_offsets_need_adjustment): New function.
|
||||||
|
(Output_section::input_sections): Make public.
|
||||||
|
* powerpc.cc (class Output_data_brlt_powerpc): New.
|
||||||
|
(class Stub_table, class Stub_control): New.
|
||||||
|
(Powerpc_relobj::has14_, set_has_14bit_branch, has_14bit_branch,
|
||||||
|
stub_table_, set_stub_table, stub_table): New vectors and accessor
|
||||||
|
functions.
|
||||||
|
(Target_powerpc::do_may_relax, do_relax, push_branch,
|
||||||
|
new_stub_table, stub_tables, brlt_section, group_sections,
|
||||||
|
add_branch_lookup_table, find_branch_lookup_table,
|
||||||
|
write_branch_lookup_table, make_brlt_section): New functions.
|
||||||
|
(Target_powerpc::struct Sort_sections, class Branch_info): New.
|
||||||
|
(Target_powerpc::brlt_section_, stub_tables_, branch_lookup_table_,
|
||||||
|
branch_info_): New vars.
|
||||||
|
(Target_powerpc::make_plt_entry, make_local_ifunc_plt_entry): Don't
|
||||||
|
make call stubs here.
|
||||||
|
(Output_data_glink): Remove all call stub handling from this class.
|
||||||
|
(Target_powerpc::Scan::local, global): Save interesting branch
|
||||||
|
relocs and relocs for ifunc. Adjust calls to plt entry functions.
|
||||||
|
(Target_powerpc::do_finalize_sections): Only make reg save/restore
|
||||||
|
functions on final link.
|
||||||
|
(Target_powerpc::Relocate::relocate): Adjust lookup of call stubs.
|
||||||
|
Handle long branch destinations too.
|
||||||
|
(Target_powerpc::do_dynsym_value, do_plt_address_for_global,
|
||||||
|
do_plt_address_for_local): Adjust lookup of plt call stubs.
|
||||||
|
|
||||||
2012-11-30 Alan Modra <amodra@gmail.com>
|
2012-11-30 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* powerpc.c (Target_powerpc::Scan::global): Don't emit relative
|
* powerpc.c (Target_powerpc::Scan::global): Don't emit relative
|
||||||
|
|
|
@ -5644,10 +5644,6 @@ Arm_output_section<big_endian>::group_sections(
|
||||||
Target_arm<big_endian>* target,
|
Target_arm<big_endian>* target,
|
||||||
const Task* task)
|
const Task* task)
|
||||||
{
|
{
|
||||||
// We only care about sections containing code.
|
|
||||||
if ((this->flags() & elfcpp::SHF_EXECINSTR) == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// States for grouping.
|
// States for grouping.
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
@ -11442,7 +11438,7 @@ Target_arm<big_endian>::group_sections(
|
||||||
{
|
{
|
||||||
// Group input sections and insert stub table
|
// Group input sections and insert stub table
|
||||||
Layout::Section_list section_list;
|
Layout::Section_list section_list;
|
||||||
layout->get_allocated_sections(§ion_list);
|
layout->get_executable_sections(§ion_list);
|
||||||
for (Layout::Section_list::const_iterator p = section_list.begin();
|
for (Layout::Section_list::const_iterator p = section_list.begin();
|
||||||
p != section_list.end();
|
p != section_list.end();
|
||||||
++p)
|
++p)
|
||||||
|
|
|
@ -5004,6 +5004,19 @@ Layout::get_allocated_sections(Section_list* section_list) const
|
||||||
section_list->push_back(*p);
|
section_list->push_back(*p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store the executable sections into the section list.
|
||||||
|
|
||||||
|
void
|
||||||
|
Layout::get_executable_sections(Section_list* section_list) const
|
||||||
|
{
|
||||||
|
for (Section_list::const_iterator p = this->section_list_.begin();
|
||||||
|
p != this->section_list_.end();
|
||||||
|
++p)
|
||||||
|
if (((*p)->flags() & (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR))
|
||||||
|
== (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR))
|
||||||
|
section_list->push_back(*p);
|
||||||
|
}
|
||||||
|
|
||||||
// Create an output segment.
|
// Create an output segment.
|
||||||
|
|
||||||
Output_segment*
|
Output_segment*
|
||||||
|
|
|
@ -917,6 +917,10 @@ class Layout
|
||||||
void
|
void
|
||||||
get_allocated_sections(Section_list*) const;
|
get_allocated_sections(Section_list*) const;
|
||||||
|
|
||||||
|
// Store the executable sections into the section list.
|
||||||
|
void
|
||||||
|
get_executable_sections(Section_list*) const;
|
||||||
|
|
||||||
// Make a section for a linker script to hold data.
|
// Make a section for a linker script to hold data.
|
||||||
Output_section*
|
Output_section*
|
||||||
make_output_section_for_script(const char* name,
|
make_output_section_for_script(const char* name,
|
||||||
|
|
|
@ -851,15 +851,16 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
|
||||||
os->set_needs_symtab_index();
|
os->set_needs_symtab_index();
|
||||||
}
|
}
|
||||||
|
|
||||||
// An absolute relocation.
|
// An absolute or relative relocation.
|
||||||
|
|
||||||
template<bool dynamic, int size, bool big_endian>
|
template<bool dynamic, int size, bool big_endian>
|
||||||
Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
|
Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
|
||||||
unsigned int type,
|
unsigned int type,
|
||||||
Output_data* od,
|
Output_data* od,
|
||||||
Address address)
|
Address address,
|
||||||
|
bool is_relative)
|
||||||
: address_(address), local_sym_index_(0), type_(type),
|
: address_(address), local_sym_index_(0), type_(type),
|
||||||
is_relative_(false), is_symbolless_(false),
|
is_relative_(is_relative), is_symbolless_(false),
|
||||||
is_section_symbol_(false), use_plt_offset_(false), shndx_(INVALID_CODE)
|
is_section_symbol_(false), use_plt_offset_(false), shndx_(INVALID_CODE)
|
||||||
{
|
{
|
||||||
// this->type_ is a bitfield; make sure TYPE fits.
|
// this->type_ is a bitfield; make sure TYPE fits.
|
||||||
|
@ -873,9 +874,10 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
|
||||||
unsigned int type,
|
unsigned int type,
|
||||||
Sized_relobj<size, big_endian>* relobj,
|
Sized_relobj<size, big_endian>* relobj,
|
||||||
unsigned int shndx,
|
unsigned int shndx,
|
||||||
Address address)
|
Address address,
|
||||||
|
bool is_relative)
|
||||||
: address_(address), local_sym_index_(0), type_(type),
|
: address_(address), local_sym_index_(0), type_(type),
|
||||||
is_relative_(false), is_symbolless_(false),
|
is_relative_(is_relative), is_symbolless_(false),
|
||||||
is_section_symbol_(false), use_plt_offset_(false), shndx_(shndx)
|
is_section_symbol_(false), use_plt_offset_(false), shndx_(shndx)
|
||||||
{
|
{
|
||||||
gold_assert(shndx != INVALID_CODE);
|
gold_assert(shndx != INVALID_CODE);
|
||||||
|
|
104
gold/output.h
104
gold/output.h
|
@ -103,8 +103,8 @@ class Output_data
|
||||||
return this->offset_;
|
return this->offset_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the address and file offset. This essentially disables the
|
// Reset the address, file offset and data size. This essentially
|
||||||
// sanity testing about duplicate and unknown settings.
|
// disables the sanity testing about duplicate and unknown settings.
|
||||||
void
|
void
|
||||||
reset_address_and_file_offset()
|
reset_address_and_file_offset()
|
||||||
{
|
{
|
||||||
|
@ -115,6 +115,14 @@ class Output_data
|
||||||
this->do_reset_address_and_file_offset();
|
this->do_reset_address_and_file_offset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// As above, but just for data size.
|
||||||
|
void
|
||||||
|
reset_data_size()
|
||||||
|
{
|
||||||
|
if (!this->is_data_size_fixed_)
|
||||||
|
this->is_data_size_valid_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
// Return true if address and file offset already have reset values. In
|
// Return true if address and file offset already have reset values. In
|
||||||
// other words, calling reset_address_and_file_offset will not change them.
|
// other words, calling reset_address_and_file_offset will not change them.
|
||||||
bool
|
bool
|
||||||
|
@ -1052,12 +1060,13 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
||||||
Sized_relobj<size, big_endian>* relobj, unsigned int shndx,
|
Sized_relobj<size, big_endian>* relobj, unsigned int shndx,
|
||||||
Address address, bool is_relative);
|
Address address, bool is_relative);
|
||||||
|
|
||||||
// An absolute relocation with no symbol.
|
// An absolute or relative relocation with no symbol.
|
||||||
|
|
||||||
Output_reloc(unsigned int type, Output_data* od, Address address);
|
Output_reloc(unsigned int type, Output_data* od, Address address,
|
||||||
|
bool is_relative);
|
||||||
|
|
||||||
Output_reloc(unsigned int type, Sized_relobj<size, big_endian>* relobj,
|
Output_reloc(unsigned int type, Sized_relobj<size, big_endian>* relobj,
|
||||||
unsigned int shndx, Address address);
|
unsigned int shndx, Address address, bool is_relative);
|
||||||
|
|
||||||
// A target specific relocation. The target will be called to get
|
// A target specific relocation. The target will be called to get
|
||||||
// the symbol index, passing ARG. The type and offset will be set
|
// the symbol index, passing ARG. The type and offset will be set
|
||||||
|
@ -1307,16 +1316,17 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
|
||||||
: rel_(os, type, relobj, shndx, address, is_relative), addend_(addend)
|
: rel_(os, type, relobj, shndx, address, is_relative), addend_(addend)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
// An absolute relocation with no symbol.
|
// An absolute or relative relocation with no symbol.
|
||||||
|
|
||||||
Output_reloc(unsigned int type, Output_data* od, Address address,
|
Output_reloc(unsigned int type, Output_data* od, Address address,
|
||||||
Addend addend)
|
Addend addend, bool is_relative)
|
||||||
: rel_(type, od, address), addend_(addend)
|
: rel_(type, od, address, is_relative), addend_(addend)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Output_reloc(unsigned int type, Sized_relobj<size, big_endian>* relobj,
|
Output_reloc(unsigned int type, Sized_relobj<size, big_endian>* relobj,
|
||||||
unsigned int shndx, Address address, Addend addend)
|
unsigned int shndx, Address address, Addend addend,
|
||||||
: rel_(type, relobj, shndx, address), addend_(addend)
|
bool is_relative)
|
||||||
|
: rel_(type, relobj, shndx, address, is_relative), addend_(addend)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
// A target specific relocation. The target will be called to get
|
// A target specific relocation. The target will be called to get
|
||||||
|
@ -1797,13 +1807,25 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
||||||
|
|
||||||
void
|
void
|
||||||
add_absolute(unsigned int type, Output_data* od, Address address)
|
add_absolute(unsigned int type, Output_data* od, Address address)
|
||||||
{ this->add(od, Output_reloc_type(type, od, address)); }
|
{ this->add(od, Output_reloc_type(type, od, address, false)); }
|
||||||
|
|
||||||
void
|
void
|
||||||
add_absolute(unsigned int type, Output_data* od,
|
add_absolute(unsigned int type, Output_data* od,
|
||||||
Sized_relobj<size, big_endian>* relobj,
|
Sized_relobj<size, big_endian>* relobj,
|
||||||
unsigned int shndx, Address address)
|
unsigned int shndx, Address address)
|
||||||
{ this->add(od, Output_reloc_type(type, relobj, shndx, address)); }
|
{ this->add(od, Output_reloc_type(type, relobj, shndx, address, false)); }
|
||||||
|
|
||||||
|
// Add a relative relocation
|
||||||
|
|
||||||
|
void
|
||||||
|
add_relative(unsigned int type, Output_data* od, Address address)
|
||||||
|
{ this->add(od, Output_reloc_type(type, od, address, true)); }
|
||||||
|
|
||||||
|
void
|
||||||
|
add_relative(unsigned int type, Output_data* od,
|
||||||
|
Sized_relobj<size, big_endian>* relobj,
|
||||||
|
unsigned int shndx, Address address)
|
||||||
|
{ this->add(od, Output_reloc_type(type, relobj, shndx, address, true)); }
|
||||||
|
|
||||||
// Add a target specific relocation. A target which calls this must
|
// Add a target specific relocation. A target which calls this must
|
||||||
// define the reloc_symbol_index and reloc_addend virtual functions.
|
// define the reloc_symbol_index and reloc_addend virtual functions.
|
||||||
|
@ -2095,13 +2117,28 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
|
||||||
void
|
void
|
||||||
add_absolute(unsigned int type, Output_data* od, Address address,
|
add_absolute(unsigned int type, Output_data* od, Address address,
|
||||||
Addend addend)
|
Addend addend)
|
||||||
{ this->add(od, Output_reloc_type(type, od, address, addend)); }
|
{ this->add(od, Output_reloc_type(type, od, address, addend, false)); }
|
||||||
|
|
||||||
void
|
void
|
||||||
add_absolute(unsigned int type, Output_data* od,
|
add_absolute(unsigned int type, Output_data* od,
|
||||||
Sized_relobj<size, big_endian>* relobj,
|
Sized_relobj<size, big_endian>* relobj,
|
||||||
unsigned int shndx, Address address, Addend addend)
|
unsigned int shndx, Address address, Addend addend)
|
||||||
{ this->add(od, Output_reloc_type(type, relobj, shndx, address, addend)); }
|
{ this->add(od, Output_reloc_type(type, relobj, shndx, address, addend,
|
||||||
|
false)); }
|
||||||
|
|
||||||
|
// Add a relative relocation
|
||||||
|
|
||||||
|
void
|
||||||
|
add_relative(unsigned int type, Output_data* od, Address address,
|
||||||
|
Addend addend)
|
||||||
|
{ this->add(od, Output_reloc_type(type, od, address, addend, true)); }
|
||||||
|
|
||||||
|
void
|
||||||
|
add_relative(unsigned int type, Output_data* od,
|
||||||
|
Sized_relobj<size, big_endian>* relobj,
|
||||||
|
unsigned int shndx, Address address, Addend addend)
|
||||||
|
{ this->add(od, Output_reloc_type(type, relobj, shndx, address, addend,
|
||||||
|
true)); }
|
||||||
|
|
||||||
// Add a target specific relocation. A target which calls this must
|
// Add a target specific relocation. A target which calls this must
|
||||||
// define the reloc_symbol_index and reloc_addend virtual functions.
|
// define the reloc_symbol_index and reloc_addend virtual functions.
|
||||||
|
@ -2700,6 +2737,15 @@ class Output_relaxed_input_section : public Output_section_data_build
|
||||||
shndx() const
|
shndx() const
|
||||||
{ return this->shndx_; }
|
{ return this->shndx_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void
|
||||||
|
set_relobj(Relobj* relobj)
|
||||||
|
{ this->relobj_ = relobj; }
|
||||||
|
|
||||||
|
void
|
||||||
|
set_shndx(unsigned int shndx)
|
||||||
|
{ this->shndx_ = shndx; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Relobj* relobj_;
|
Relobj* relobj_;
|
||||||
unsigned int shndx_;
|
unsigned int shndx_;
|
||||||
|
@ -3162,6 +3208,13 @@ class Output_section : public Output_data
|
||||||
set_addralign(uint64_t v)
|
set_addralign(uint64_t v)
|
||||||
{ this->addralign_ = v; }
|
{ this->addralign_ = v; }
|
||||||
|
|
||||||
|
void
|
||||||
|
checkpoint_set_addralign(uint64_t val)
|
||||||
|
{
|
||||||
|
if (this->checkpoint_ != NULL)
|
||||||
|
this->checkpoint_->set_addralign(val);
|
||||||
|
}
|
||||||
|
|
||||||
// Whether the output section index has been set.
|
// Whether the output section index has been set.
|
||||||
bool
|
bool
|
||||||
has_out_shndx() const
|
has_out_shndx() const
|
||||||
|
@ -3794,6 +3847,11 @@ class Output_section : public Output_data
|
||||||
set_section_offsets_need_adjustment()
|
set_section_offsets_need_adjustment()
|
||||||
{ this->section_offsets_need_adjustment_ = true; }
|
{ this->section_offsets_need_adjustment_ = true; }
|
||||||
|
|
||||||
|
// Set section_offsets_need_adjustment to be false.
|
||||||
|
void
|
||||||
|
clear_section_offsets_need_adjustment()
|
||||||
|
{ this->section_offsets_need_adjustment_ = false; }
|
||||||
|
|
||||||
// Adjust section offsets of input sections in this. This is
|
// Adjust section offsets of input sections in this. This is
|
||||||
// requires if relaxation caused some input sections to change sizes.
|
// requires if relaxation caused some input sections to change sizes.
|
||||||
void
|
void
|
||||||
|
@ -3848,6 +3906,13 @@ class Output_section : public Output_data
|
||||||
off_t
|
off_t
|
||||||
allocate(off_t len, uint64_t addralign);
|
allocate(off_t len, uint64_t addralign);
|
||||||
|
|
||||||
|
typedef std::vector<Input_section> Input_section_list;
|
||||||
|
|
||||||
|
// Allow access to the input sections.
|
||||||
|
const Input_section_list&
|
||||||
|
input_sections() const
|
||||||
|
{ return this->input_sections_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Return the output section--i.e., the object itself.
|
// Return the output section--i.e., the object itself.
|
||||||
Output_section*
|
Output_section*
|
||||||
|
@ -3970,13 +4035,6 @@ class Output_section : public Output_data
|
||||||
void
|
void
|
||||||
write_to_postprocessing_buffer();
|
write_to_postprocessing_buffer();
|
||||||
|
|
||||||
typedef std::vector<Input_section> Input_section_list;
|
|
||||||
|
|
||||||
// Allow a child class to access the input sections.
|
|
||||||
const Input_section_list&
|
|
||||||
input_sections() const
|
|
||||||
{ return this->input_sections_; }
|
|
||||||
|
|
||||||
// Whether this always keeps an input section list
|
// Whether this always keeps an input section list
|
||||||
bool
|
bool
|
||||||
always_keeps_input_sections() const
|
always_keeps_input_sections() const
|
||||||
|
@ -4015,6 +4073,10 @@ class Output_section : public Output_data
|
||||||
addralign() const
|
addralign() const
|
||||||
{ return this->addralign_; }
|
{ return this->addralign_; }
|
||||||
|
|
||||||
|
void
|
||||||
|
set_addralign(uint64_t val)
|
||||||
|
{ this->addralign_ = val; }
|
||||||
|
|
||||||
// Return the section flags.
|
// Return the section flags.
|
||||||
elfcpp::Elf_Xword
|
elfcpp::Elf_Xword
|
||||||
flags() const
|
flags() const
|
||||||
|
|
1977
gold/powerpc.cc
1977
gold/powerpc.cc
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue