* 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:
Alan Modra 2012-12-03 05:30:59 +00:00
parent 0f6752b51f
commit ec661b9dca
7 changed files with 1680 additions and 477 deletions

View file

@ -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

View file

@ -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(&section_list); layout->get_executable_sections(&section_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)

View file

@ -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*

View file

@ -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,

View file

@ -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);

View file

@ -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

File diff suppressed because it is too large Load diff