From Cary Coutant: Count textrel with output sections rather than
setting a flag as we add each reloc in the target code.
This commit is contained in:
parent
02d2ba7402
commit
4f4c5f80c7
8 changed files with 151 additions and 89 deletions
44
gold/i386.cc
44
gold/i386.cc
|
@ -288,7 +288,7 @@ class Target_i386 : public Sized_target<32, false>
|
||||||
void
|
void
|
||||||
copy_reloc(const General_options*, Symbol_table*, Layout*,
|
copy_reloc(const General_options*, Symbol_table*, Layout*,
|
||||||
Sized_relobj<32, false>*, unsigned int,
|
Sized_relobj<32, false>*, unsigned int,
|
||||||
Symbol*, const elfcpp::Rel<32, false>&);
|
Output_section*, Symbol*, const elfcpp::Rel<32, false>&);
|
||||||
|
|
||||||
// Information about this specific target which we pass to the
|
// Information about this specific target which we pass to the
|
||||||
// general Target structure.
|
// general Target structure.
|
||||||
|
@ -652,7 +652,9 @@ Target_i386::copy_reloc(const General_options* options,
|
||||||
Symbol_table* symtab,
|
Symbol_table* symtab,
|
||||||
Layout* layout,
|
Layout* layout,
|
||||||
Sized_relobj<32, false>* object,
|
Sized_relobj<32, false>* object,
|
||||||
unsigned int data_shndx, Symbol* gsym,
|
unsigned int data_shndx,
|
||||||
|
Output_section* output_section,
|
||||||
|
Symbol* gsym,
|
||||||
const elfcpp::Rel<32, false>& rel)
|
const elfcpp::Rel<32, false>& rel)
|
||||||
{
|
{
|
||||||
Sized_symbol<32>* ssym;
|
Sized_symbol<32>* ssym;
|
||||||
|
@ -667,7 +669,7 @@ Target_i386::copy_reloc(const General_options* options,
|
||||||
// symbol, then we will emit the relocation.
|
// symbol, then we will emit the relocation.
|
||||||
if (this->copy_relocs_ == NULL)
|
if (this->copy_relocs_ == NULL)
|
||||||
this->copy_relocs_ = new Copy_relocs<32, false>();
|
this->copy_relocs_ = new Copy_relocs<32, false>();
|
||||||
this->copy_relocs_->save(ssym, object, data_shndx, rel);
|
this->copy_relocs_->save(ssym, object, data_shndx, output_section, rel);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -809,10 +811,8 @@ Target_i386::Scan::local(const General_options&,
|
||||||
if (parameters->output_is_position_independent())
|
if (parameters->output_is_position_independent())
|
||||||
{
|
{
|
||||||
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
|
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
|
||||||
rel_dyn->add_local(object, 0, elfcpp::R_386_RELATIVE, data_shndx,
|
rel_dyn->add_local(object, 0, elfcpp::R_386_RELATIVE, output_section,
|
||||||
reloc.get_r_offset());
|
data_shndx, reloc.get_r_offset());
|
||||||
if (!output_section->is_section_flag_set(elfcpp::SHF_WRITE))
|
|
||||||
layout->set_have_textrel();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -827,10 +827,8 @@ Target_i386::Scan::local(const General_options&,
|
||||||
{
|
{
|
||||||
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());
|
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
|
||||||
rel_dyn->add_local(object, r_sym, r_type, data_shndx,
|
rel_dyn->add_local(object, r_sym, r_type, output_section, data_shndx,
|
||||||
reloc.get_r_offset());
|
reloc.get_r_offset());
|
||||||
if (!output_section->is_section_flag_set(elfcpp::SHF_WRITE))
|
|
||||||
layout->set_have_textrel();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -863,9 +861,8 @@ Target_i386::Scan::local(const General_options&,
|
||||||
{
|
{
|
||||||
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
|
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
|
||||||
rel_dyn->add_local(object, 0, elfcpp::R_386_RELATIVE,
|
rel_dyn->add_local(object, 0, elfcpp::R_386_RELATIVE,
|
||||||
data_shndx, reloc.get_r_offset());
|
output_section, data_shndx,
|
||||||
if (!output_section->is_section_flag_set(elfcpp::SHF_WRITE))
|
reloc.get_r_offset());
|
||||||
layout->set_have_textrel();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1064,24 +1061,21 @@ Target_i386::Scan::global(const General_options& options,
|
||||||
if (target->may_need_copy_reloc(gsym))
|
if (target->may_need_copy_reloc(gsym))
|
||||||
{
|
{
|
||||||
target->copy_reloc(&options, symtab, layout, object,
|
target->copy_reloc(&options, symtab, layout, object,
|
||||||
data_shndx, gsym, reloc);
|
data_shndx, output_section, gsym, reloc);
|
||||||
}
|
}
|
||||||
else if (r_type == elfcpp::R_386_32
|
else if (r_type == elfcpp::R_386_32
|
||||||
&& gsym->can_use_relative_reloc(false))
|
&& gsym->can_use_relative_reloc(false))
|
||||||
{
|
{
|
||||||
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
|
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
|
||||||
rel_dyn->add_local(object, 0, elfcpp::R_386_RELATIVE,
|
rel_dyn->add_local(object, 0, elfcpp::R_386_RELATIVE,
|
||||||
data_shndx, reloc.get_r_offset());
|
output_section, data_shndx,
|
||||||
if (!output_section->is_section_flag_set(elfcpp::SHF_WRITE))
|
reloc.get_r_offset());
|
||||||
layout->set_have_textrel();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
|
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
|
||||||
rel_dyn->add_global(gsym, r_type, object, data_shndx,
|
rel_dyn->add_global(gsym, r_type, output_section, object,
|
||||||
reloc.get_r_offset());
|
data_shndx, reloc.get_r_offset());
|
||||||
if (!output_section->is_section_flag_set(elfcpp::SHF_WRITE))
|
|
||||||
layout->set_have_textrel();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1101,15 +1095,13 @@ Target_i386::Scan::global(const General_options& options,
|
||||||
if (target->may_need_copy_reloc(gsym))
|
if (target->may_need_copy_reloc(gsym))
|
||||||
{
|
{
|
||||||
target->copy_reloc(&options, symtab, layout, object,
|
target->copy_reloc(&options, symtab, layout, object,
|
||||||
data_shndx, gsym, reloc);
|
data_shndx, output_section, gsym, reloc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
|
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
|
||||||
rel_dyn->add_global(gsym, r_type, object, data_shndx,
|
rel_dyn->add_global(gsym, r_type, output_section, object,
|
||||||
reloc.get_r_offset());
|
data_shndx, reloc.get_r_offset());
|
||||||
if (!output_section->is_section_flag_set(elfcpp::SHF_WRITE))
|
|
||||||
layout->set_have_textrel();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,8 +70,7 @@ Layout::Layout(const General_options& options)
|
||||||
eh_frame_section_(NULL), output_file_size_(-1),
|
eh_frame_section_(NULL), output_file_size_(-1),
|
||||||
input_requires_executable_stack_(false),
|
input_requires_executable_stack_(false),
|
||||||
input_with_gnu_stack_note_(false),
|
input_with_gnu_stack_note_(false),
|
||||||
input_without_gnu_stack_note_(false),
|
input_without_gnu_stack_note_(false)
|
||||||
have_textrel_(false)
|
|
||||||
{
|
{
|
||||||
// Make space for more than enough segments for a typical file.
|
// Make space for more than enough segments for a typical file.
|
||||||
// This is just for efficiency--it's OK if we wind up needing more.
|
// This is just for efficiency--it's OK if we wind up needing more.
|
||||||
|
@ -1618,13 +1617,27 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
|
||||||
|
|
||||||
odyn->add_string(elfcpp::DT_RPATH, rpath_val);
|
odyn->add_string(elfcpp::DT_RPATH, rpath_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a DT_FLAGS entry. We add it even if no flags are set so that
|
// Look for text segments that have dynamic relocations.
|
||||||
// post-link tools can easily modify these flags if desired.
|
bool have_textrel = false;
|
||||||
unsigned int flags = 0;
|
for (Segment_list::const_iterator p = this->segment_list_.begin();
|
||||||
if (this->have_textrel_)
|
p != this->segment_list_.end();
|
||||||
flags |= elfcpp::DF_TEXTREL;
|
++p)
|
||||||
odyn->add_constant(elfcpp::DT_FLAGS, flags);
|
{
|
||||||
|
if (((*p)->flags() & elfcpp::PF_W) == 0
|
||||||
|
&& (*p)->dynamic_reloc_count() > 0)
|
||||||
|
{
|
||||||
|
have_textrel = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a DT_FLAGS entry. We add it even if no flags are set so that
|
||||||
|
// post-link tools can easily modify these flags if desired.
|
||||||
|
unsigned int flags = 0;
|
||||||
|
if (have_textrel)
|
||||||
|
flags |= elfcpp::DF_TEXTREL;
|
||||||
|
odyn->add_constant(elfcpp::DT_FLAGS, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The mapping of .gnu.linkonce section names to real section names.
|
// The mapping of .gnu.linkonce section names to real section names.
|
||||||
|
|
|
@ -170,11 +170,6 @@ class Layout
|
||||||
off_t
|
off_t
|
||||||
finalize(const Input_objects*, Symbol_table*);
|
finalize(const Input_objects*, Symbol_table*);
|
||||||
|
|
||||||
// Record that we have seen a relocation in the text section.
|
|
||||||
void
|
|
||||||
set_have_textrel()
|
|
||||||
{ this->have_textrel_ = true; }
|
|
||||||
|
|
||||||
// Return the size of the output file.
|
// Return the size of the output file.
|
||||||
off_t
|
off_t
|
||||||
output_file_size() const
|
output_file_size() const
|
||||||
|
@ -439,8 +434,6 @@ class Layout
|
||||||
// Whether we have seen at least one object file without an
|
// Whether we have seen at least one object file without an
|
||||||
// executable stack marker.
|
// executable stack marker.
|
||||||
bool input_without_gnu_stack_note_;
|
bool input_without_gnu_stack_note_;
|
||||||
// Whether we have seen a relocation in the text section.
|
|
||||||
bool have_textrel_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// This task handles writing out data in output sections which is not
|
// This task handles writing out data in output sections which is not
|
||||||
|
|
|
@ -1580,6 +1580,28 @@ Output_segment::maximum_alignment(const Output_data_list* pdl)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the number of dynamic relocs applied to this segment.
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
Output_segment::dynamic_reloc_count() const
|
||||||
|
{
|
||||||
|
return (this->dynamic_reloc_count_list(&this->output_data_)
|
||||||
|
+ this->dynamic_reloc_count_list(&this->output_bss_));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the number of dynamic relocs applied to an Output_data_list.
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
Output_segment::dynamic_reloc_count_list(const Output_data_list* pdl) const
|
||||||
|
{
|
||||||
|
unsigned int count = 0;
|
||||||
|
for (Output_data_list::const_iterator p = pdl->begin();
|
||||||
|
p != pdl->end();
|
||||||
|
++p)
|
||||||
|
count += (*p)->dynamic_reloc_count();
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
// Set the section addresses for an Output_segment. ADDR is the
|
// Set the section addresses for an Output_segment. ADDR is the
|
||||||
// address and *POFF is the file offset. Set the section indexes
|
// address and *POFF is the file offset. Set the section indexes
|
||||||
// starting with *PSHNDX. Return the address of the immediately
|
// starting with *PSHNDX. Return the address of the immediately
|
||||||
|
|
|
@ -50,7 +50,8 @@ class Output_data
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Output_data(off_t data_size = 0)
|
explicit Output_data(off_t data_size = 0)
|
||||||
: address_(0), data_size_(data_size), offset_(-1)
|
: address_(0), data_size_(data_size), offset_(-1),
|
||||||
|
dynamic_reloc_count_(0)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
virtual
|
virtual
|
||||||
|
@ -128,6 +129,16 @@ class Output_data
|
||||||
is_layout_complete()
|
is_layout_complete()
|
||||||
{ return Output_data::sizes_are_fixed; }
|
{ return Output_data::sizes_are_fixed; }
|
||||||
|
|
||||||
|
// Count the number of dynamic relocations applied to this section.
|
||||||
|
void
|
||||||
|
add_dynamic_reloc()
|
||||||
|
{ ++this->dynamic_reloc_count_; }
|
||||||
|
|
||||||
|
// Return the number of dynamic relocations applied to this section.
|
||||||
|
unsigned int
|
||||||
|
dynamic_reloc_count() const
|
||||||
|
{ return this->dynamic_reloc_count_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Functions that child classes may or in some cases must implement.
|
// Functions that child classes may or in some cases must implement.
|
||||||
|
|
||||||
|
@ -205,6 +216,8 @@ class Output_data
|
||||||
off_t data_size_;
|
off_t data_size_;
|
||||||
// Offset within file.
|
// Offset within file.
|
||||||
off_t offset_;
|
off_t offset_;
|
||||||
|
// Count of dynamic relocations applied to this section.
|
||||||
|
unsigned int dynamic_reloc_count_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Output the section headers.
|
// Output the section headers.
|
||||||
|
@ -754,10 +767,11 @@ class Output_data_reloc_base : public Output_section_data
|
||||||
|
|
||||||
// Add a relocation entry.
|
// Add a relocation entry.
|
||||||
void
|
void
|
||||||
add(const Output_reloc_type& reloc)
|
add(Output_data *od, const Output_reloc_type& reloc)
|
||||||
{
|
{
|
||||||
this->relocs_.push_back(reloc);
|
this->relocs_.push_back(reloc);
|
||||||
this->set_data_size(this->relocs_.size() * reloc_size);
|
this->set_data_size(this->relocs_.size() * reloc_size);
|
||||||
|
od->add_dynamic_reloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -793,12 +807,12 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
||||||
|
|
||||||
void
|
void
|
||||||
add_global(Symbol* gsym, unsigned int type, Output_data* od, Address address)
|
add_global(Symbol* gsym, unsigned int type, Output_data* od, Address address)
|
||||||
{ this->add(Output_reloc_type(gsym, type, od, address)); }
|
{ this->add(od, Output_reloc_type(gsym, type, od, address)); }
|
||||||
|
|
||||||
void
|
void
|
||||||
add_global(Symbol* gsym, unsigned int type, Relobj* relobj,
|
add_global(Symbol* gsym, unsigned int type, Output_data* od, Relobj* relobj,
|
||||||
unsigned int shndx, Address address)
|
unsigned int shndx, Address address)
|
||||||
{ this->add(Output_reloc_type(gsym, type, relobj, shndx, address)); }
|
{ this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address)); }
|
||||||
|
|
||||||
// Add a reloc against a local symbol.
|
// Add a reloc against a local symbol.
|
||||||
|
|
||||||
|
@ -806,27 +820,30 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
||||||
add_local(Sized_relobj<size, big_endian>* relobj,
|
add_local(Sized_relobj<size, big_endian>* relobj,
|
||||||
unsigned int local_sym_index, unsigned int type,
|
unsigned int local_sym_index, unsigned int type,
|
||||||
Output_data* od, Address address)
|
Output_data* od, Address address)
|
||||||
{ this->add(Output_reloc_type(relobj, local_sym_index, type, od, address)); }
|
{ this->add(od, Output_reloc_type(relobj, local_sym_index, type, od,
|
||||||
|
address)); }
|
||||||
|
|
||||||
void
|
void
|
||||||
add_local(Sized_relobj<size, big_endian>* relobj,
|
add_local(Sized_relobj<size, big_endian>* relobj,
|
||||||
unsigned int local_sym_index, unsigned int type,
|
unsigned int local_sym_index, unsigned int type,
|
||||||
unsigned int shndx, Address address)
|
Output_data* od, unsigned int shndx, Address address)
|
||||||
{ this->add(Output_reloc_type(relobj, local_sym_index, type, shndx,
|
{ this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
|
||||||
address)); }
|
address)); }
|
||||||
|
|
||||||
|
|
||||||
// A reloc against the STT_SECTION symbol of an output section.
|
// A reloc against the STT_SECTION symbol of an output section.
|
||||||
|
// OS is the Output_section that the relocation refers to; OD is
|
||||||
|
// the Output_data object being relocated.
|
||||||
|
|
||||||
void
|
void
|
||||||
add_output_section(Output_section* os, unsigned int type,
|
add_output_section(Output_section* os, unsigned int type,
|
||||||
Output_data* od, Address address)
|
Output_data* od, Address address)
|
||||||
{ this->add(Output_reloc_type(os, type, od, address)); }
|
{ this->add(od, Output_reloc_type(os, type, od, address)); }
|
||||||
|
|
||||||
void
|
void
|
||||||
add_output_section(Output_section* os, unsigned int type,
|
add_output_section(Output_section* os, unsigned int type, Output_data* od,
|
||||||
Relobj* relobj, unsigned int shndx, Address address)
|
Relobj* relobj, unsigned int shndx, Address address)
|
||||||
{ this->add(Output_reloc_type(os, type, relobj, shndx, address)); }
|
{ this->add(od, Output_reloc_type(os, type, relobj, shndx, address)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// The SHT_RELA version of Output_data_reloc.
|
// The SHT_RELA version of Output_data_reloc.
|
||||||
|
@ -853,12 +870,14 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
|
||||||
void
|
void
|
||||||
add_global(Symbol* gsym, unsigned int type, Output_data* od,
|
add_global(Symbol* gsym, unsigned int type, Output_data* od,
|
||||||
Address address, Addend addend)
|
Address address, Addend addend)
|
||||||
{ this->add(Output_reloc_type(gsym, type, od, address, addend)); }
|
{ this->add(od, Output_reloc_type(gsym, type, od, address, addend)); }
|
||||||
|
|
||||||
void
|
void
|
||||||
add_global(Symbol* gsym, unsigned int type, Relobj* relobj,
|
add_global(Symbol* gsym, unsigned int type, Output_data* od, Relobj* relobj,
|
||||||
unsigned int shndx, Address address, Addend addend)
|
unsigned int shndx, Address address,
|
||||||
{ this->add(Output_reloc_type(gsym, type, relobj, shndx, address, addend)); }
|
Addend addend)
|
||||||
|
{ this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
|
||||||
|
addend)); }
|
||||||
|
|
||||||
// Add a reloc against a local symbol.
|
// Add a reloc against a local symbol.
|
||||||
|
|
||||||
|
@ -867,17 +886,18 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
|
||||||
unsigned int local_sym_index, unsigned int type,
|
unsigned int local_sym_index, unsigned int type,
|
||||||
Output_data* od, Address address, Addend addend)
|
Output_data* od, Address address, Addend addend)
|
||||||
{
|
{
|
||||||
this->add(Output_reloc_type(relobj, local_sym_index, type, od, address,
|
this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, address,
|
||||||
addend));
|
addend));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
add_local(Sized_relobj<size, big_endian>* relobj,
|
add_local(Sized_relobj<size, big_endian>* relobj,
|
||||||
unsigned int local_sym_index, unsigned int type,
|
unsigned int local_sym_index, unsigned int type,
|
||||||
unsigned int shndx, Address address, Addend addend)
|
Output_data* od, unsigned int shndx, Address address,
|
||||||
|
Addend addend)
|
||||||
{
|
{
|
||||||
this->add(Output_reloc_type(relobj, local_sym_index, type, shndx, address,
|
this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
|
||||||
addend));
|
address, addend));
|
||||||
}
|
}
|
||||||
|
|
||||||
// A reloc against the STT_SECTION symbol of an output section.
|
// A reloc against the STT_SECTION symbol of an output section.
|
||||||
|
@ -885,12 +905,13 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
|
||||||
void
|
void
|
||||||
add_output_section(Output_section* os, unsigned int type, Output_data* od,
|
add_output_section(Output_section* os, unsigned int type, Output_data* od,
|
||||||
Address address, Addend addend)
|
Address address, Addend addend)
|
||||||
{ this->add(Output_reloc_type(os, type, od, address, addend)); }
|
{ this->add(os, Output_reloc_type(os, type, od, address, addend)); }
|
||||||
|
|
||||||
void
|
void
|
||||||
add_output_section(Output_section* os, unsigned int type, Relobj* relobj,
|
add_output_section(Output_section* os, unsigned int type, Relobj* relobj,
|
||||||
unsigned int shndx, Address address, Addend addend)
|
unsigned int shndx, Address address, Addend addend)
|
||||||
{ this->add(Output_reloc_type(os, type, relobj, shndx, address, addend)); }
|
{ this->add(os, Output_reloc_type(os, type, relobj, shndx, address,
|
||||||
|
addend)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Output_data_got is used to manage a GOT. Each entry in the GOT is
|
// Output_data_got is used to manage a GOT. Each entry in the GOT is
|
||||||
|
@ -1755,6 +1776,10 @@ class Output_segment
|
||||||
void
|
void
|
||||||
add_initial_output_data(Output_data*);
|
add_initial_output_data(Output_data*);
|
||||||
|
|
||||||
|
// Return the number of dynamic relocations applied to this segment.
|
||||||
|
unsigned int
|
||||||
|
dynamic_reloc_count() const;
|
||||||
|
|
||||||
// Set the address of the segment to ADDR and the offset to *POFF
|
// Set the address of the segment to ADDR and the offset to *POFF
|
||||||
// (aligned if necessary), and set the addresses and offsets of all
|
// (aligned if necessary), and set the addresses and offsets of all
|
||||||
// contained output sections accordingly. Set the section indexes
|
// contained output sections accordingly. Set the section indexes
|
||||||
|
@ -1817,6 +1842,10 @@ class Output_segment
|
||||||
unsigned int
|
unsigned int
|
||||||
output_section_count_list(const Output_data_list*) const;
|
output_section_count_list(const Output_data_list*) const;
|
||||||
|
|
||||||
|
// Return the number of dynamic relocs in an Output_data_list.
|
||||||
|
unsigned int
|
||||||
|
dynamic_reloc_count_list(const Output_data_list*) const;
|
||||||
|
|
||||||
// Write the section headers in the list into V.
|
// Write the section headers in the list into V.
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
unsigned char*
|
unsigned char*
|
||||||
|
|
|
@ -556,8 +556,8 @@ Copy_relocs<size, big_endian>::Copy_reloc_entry::emit(
|
||||||
Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian>* reloc_data)
|
Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian>* reloc_data)
|
||||||
{
|
{
|
||||||
this->sym_->set_needs_dynsym_entry();
|
this->sym_->set_needs_dynsym_entry();
|
||||||
reloc_data->add_global(this->sym_, this->reloc_type_, this->relobj_,
|
reloc_data->add_global(this->sym_, this->reloc_type_, this->output_section_,
|
||||||
this->shndx_, this->address_);
|
this->relobj_, this->shndx_, this->address_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit a reloc into a SHT_RELA section.
|
// Emit a reloc into a SHT_RELA section.
|
||||||
|
@ -568,8 +568,9 @@ Copy_relocs<size, big_endian>::Copy_reloc_entry::emit(
|
||||||
Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>* reloc_data)
|
Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>* reloc_data)
|
||||||
{
|
{
|
||||||
this->sym_->set_needs_dynsym_entry();
|
this->sym_->set_needs_dynsym_entry();
|
||||||
reloc_data->add_global(this->sym_, this->reloc_type_, this->relobj_,
|
reloc_data->add_global(this->sym_, this->reloc_type_, this->output_section_,
|
||||||
this->shndx_, this->address_, this->addend_);
|
this->relobj_, this->shndx_, this->address_,
|
||||||
|
this->addend_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy_relocs methods.
|
// Copy_relocs methods.
|
||||||
|
@ -606,11 +607,13 @@ Copy_relocs<size, big_endian>::save(
|
||||||
Symbol* sym,
|
Symbol* sym,
|
||||||
Relobj* relobj,
|
Relobj* relobj,
|
||||||
unsigned int shndx,
|
unsigned int shndx,
|
||||||
|
Output_section* output_section,
|
||||||
const elfcpp::Rel<size, big_endian>& rel)
|
const elfcpp::Rel<size, big_endian>& rel)
|
||||||
{
|
{
|
||||||
unsigned int reloc_type = elfcpp::elf_r_type<size>(rel.get_r_info());
|
unsigned int reloc_type = elfcpp::elf_r_type<size>(rel.get_r_info());
|
||||||
this->entries_.push_back(Copy_reloc_entry(sym, reloc_type, relobj, shndx,
|
this->entries_.push_back(Copy_reloc_entry(sym, reloc_type, relobj, shndx,
|
||||||
rel.get_r_offset(), 0));
|
output_section,
|
||||||
|
rel.get_r_offset(), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save a Rela reloc.
|
// Save a Rela reloc.
|
||||||
|
@ -621,10 +624,12 @@ Copy_relocs<size, big_endian>::save(
|
||||||
Symbol* sym,
|
Symbol* sym,
|
||||||
Relobj* relobj,
|
Relobj* relobj,
|
||||||
unsigned int shndx,
|
unsigned int shndx,
|
||||||
|
Output_section* output_section,
|
||||||
const elfcpp::Rela<size, big_endian>& rela)
|
const elfcpp::Rela<size, big_endian>& rela)
|
||||||
{
|
{
|
||||||
unsigned int reloc_type = elfcpp::elf_r_type<size>(rela.get_r_info());
|
unsigned int reloc_type = elfcpp::elf_r_type<size>(rela.get_r_info());
|
||||||
this->entries_.push_back(Copy_reloc_entry(sym, reloc_type, relobj, shndx,
|
this->entries_.push_back(Copy_reloc_entry(sym, reloc_type, relobj, shndx,
|
||||||
|
output_section,
|
||||||
rela.get_r_offset(),
|
rela.get_r_offset(),
|
||||||
rela.get_r_addend()));
|
rela.get_r_addend()));
|
||||||
}
|
}
|
||||||
|
|
10
gold/reloc.h
10
gold/reloc.h
|
@ -37,6 +37,7 @@ class Relobj;
|
||||||
class Read_relocs_data;
|
class Read_relocs_data;
|
||||||
class Symbol;
|
class Symbol;
|
||||||
class Layout;
|
class Layout;
|
||||||
|
class Output_section;
|
||||||
|
|
||||||
template<int size>
|
template<int size>
|
||||||
class Sized_symbol;
|
class Sized_symbol;
|
||||||
|
@ -539,12 +540,12 @@ class Copy_relocs
|
||||||
// index of the section to which the reloc is being applied.
|
// index of the section to which the reloc is being applied.
|
||||||
void
|
void
|
||||||
save(Symbol* sym, Relobj*, unsigned int shndx,
|
save(Symbol* sym, Relobj*, unsigned int shndx,
|
||||||
const elfcpp::Rel<size, big_endian>&);
|
Output_section* output_section, const elfcpp::Rel<size, big_endian>&);
|
||||||
|
|
||||||
// Save a Rela against SYM for possible emission later.
|
// Save a Rela against SYM for possible emission later.
|
||||||
void
|
void
|
||||||
save(Symbol* sym, Relobj*, unsigned int shndx,
|
save(Symbol* sym, Relobj*, unsigned int shndx,
|
||||||
const elfcpp::Rela<size, big_endian>&);
|
Output_section* output_section, const elfcpp::Rela<size, big_endian>&);
|
||||||
|
|
||||||
// Return whether there are any relocs to emit. This also discards
|
// Return whether there are any relocs to emit. This also discards
|
||||||
// entries which need not be emitted.
|
// entries which need not be emitted.
|
||||||
|
@ -567,9 +568,11 @@ class Copy_relocs
|
||||||
public:
|
public:
|
||||||
Copy_reloc_entry(Symbol* sym, unsigned int reloc_type,
|
Copy_reloc_entry(Symbol* sym, unsigned int reloc_type,
|
||||||
Relobj* relobj, unsigned int shndx,
|
Relobj* relobj, unsigned int shndx,
|
||||||
|
Output_section* output_section,
|
||||||
Address address, Addend addend)
|
Address address, Addend addend)
|
||||||
: sym_(sym), reloc_type_(reloc_type), relobj_(relobj),
|
: sym_(sym), reloc_type_(reloc_type), relobj_(relobj),
|
||||||
shndx_(shndx), address_(address), addend_(addend)
|
shndx_(shndx), output_section_(output_section),
|
||||||
|
address_(address), addend_(addend)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
// Return whether we should emit this reloc. If we should not
|
// Return whether we should emit this reloc. If we should not
|
||||||
|
@ -590,6 +593,7 @@ class Copy_relocs
|
||||||
unsigned int reloc_type_;
|
unsigned int reloc_type_;
|
||||||
Relobj* relobj_;
|
Relobj* relobj_;
|
||||||
unsigned int shndx_;
|
unsigned int shndx_;
|
||||||
|
Output_section* output_section_;
|
||||||
Address address_;
|
Address address_;
|
||||||
Addend addend_;
|
Addend addend_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -272,7 +272,7 @@ class Target_x86_64 : public Sized_target<64, false>
|
||||||
void
|
void
|
||||||
copy_reloc(const General_options*, Symbol_table*, Layout*,
|
copy_reloc(const General_options*, Symbol_table*, Layout*,
|
||||||
Sized_relobj<64, false>*, unsigned int,
|
Sized_relobj<64, false>*, unsigned int,
|
||||||
Symbol*, const elfcpp::Rela<64, false>&);
|
Output_section*, Symbol*, const elfcpp::Rela<64, false>&);
|
||||||
|
|
||||||
// Information about this specific target which we pass to the
|
// Information about this specific target which we pass to the
|
||||||
// general Target structure.
|
// general Target structure.
|
||||||
|
@ -606,7 +606,9 @@ Target_x86_64::copy_reloc(const General_options* options,
|
||||||
Symbol_table* symtab,
|
Symbol_table* symtab,
|
||||||
Layout* layout,
|
Layout* layout,
|
||||||
Sized_relobj<64, false>* object,
|
Sized_relobj<64, false>* object,
|
||||||
unsigned int data_shndx, Symbol* gsym,
|
unsigned int data_shndx,
|
||||||
|
Output_section* output_section,
|
||||||
|
Symbol* gsym,
|
||||||
const elfcpp::Rela<64, false>& rela)
|
const elfcpp::Rela<64, false>& rela)
|
||||||
{
|
{
|
||||||
Sized_symbol<64>* ssym;
|
Sized_symbol<64>* ssym;
|
||||||
|
@ -621,7 +623,7 @@ Target_x86_64::copy_reloc(const General_options* options,
|
||||||
// symbol, then we will emit the relocation.
|
// symbol, then we will emit the relocation.
|
||||||
if (this->copy_relocs_ == NULL)
|
if (this->copy_relocs_ == NULL)
|
||||||
this->copy_relocs_ = new Copy_relocs<64, false>();
|
this->copy_relocs_ = new Copy_relocs<64, false>();
|
||||||
this->copy_relocs_->save(ssym, object, data_shndx, rela);
|
this->copy_relocs_->save(ssym, object, data_shndx, output_section, rela);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -740,7 +742,7 @@ Target_x86_64::Scan::local(const General_options&,
|
||||||
Target_x86_64* target,
|
Target_x86_64* target,
|
||||||
Sized_relobj<64, false>* object,
|
Sized_relobj<64, false>* object,
|
||||||
unsigned int data_shndx,
|
unsigned int data_shndx,
|
||||||
Output_section*,
|
Output_section* output_section,
|
||||||
const elfcpp::Rela<64, false>& reloc,
|
const elfcpp::Rela<64, false>& reloc,
|
||||||
unsigned int r_type,
|
unsigned int r_type,
|
||||||
const elfcpp::Sym<64, false>&)
|
const elfcpp::Sym<64, false>&)
|
||||||
|
@ -763,7 +765,8 @@ Target_x86_64::Scan::local(const General_options&,
|
||||||
{
|
{
|
||||||
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
||||||
rela_dyn->add_local(object, 0, elfcpp::R_X86_64_RELATIVE,
|
rela_dyn->add_local(object, 0, elfcpp::R_X86_64_RELATIVE,
|
||||||
data_shndx, reloc.get_r_offset(), 0);
|
output_section, data_shndx,
|
||||||
|
reloc.get_r_offset(), 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -781,8 +784,8 @@ Target_x86_64::Scan::local(const General_options&,
|
||||||
{
|
{
|
||||||
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
||||||
unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
|
unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
|
||||||
rela_dyn->add_local(object, r_sym, r_type, data_shndx,
|
rela_dyn->add_local(object, r_sym, r_type, output_section,
|
||||||
reloc.get_r_offset(),
|
data_shndx, reloc.get_r_offset(),
|
||||||
reloc.get_r_addend());
|
reloc.get_r_addend());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -828,7 +831,8 @@ Target_x86_64::Scan::local(const General_options&,
|
||||||
|
|
||||||
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
||||||
rela_dyn->add_local(object, 0, elfcpp::R_X86_64_RELATIVE,
|
rela_dyn->add_local(object, 0, elfcpp::R_X86_64_RELATIVE,
|
||||||
data_shndx, reloc.get_r_offset(), 0);
|
output_section, data_shndx,
|
||||||
|
reloc.get_r_offset(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// For GOTPLT64, we'd normally want a PLT section, but since
|
// For GOTPLT64, we'd normally want a PLT section, but since
|
||||||
|
@ -930,7 +934,7 @@ Target_x86_64::Scan::global(const General_options& options,
|
||||||
Target_x86_64* target,
|
Target_x86_64* target,
|
||||||
Sized_relobj<64, false>* object,
|
Sized_relobj<64, false>* object,
|
||||||
unsigned int data_shndx,
|
unsigned int data_shndx,
|
||||||
Output_section*,
|
Output_section* output_section,
|
||||||
const elfcpp::Rela<64, false>& reloc,
|
const elfcpp::Rela<64, false>& reloc,
|
||||||
unsigned int r_type,
|
unsigned int r_type,
|
||||||
Symbol* gsym)
|
Symbol* gsym)
|
||||||
|
@ -965,21 +969,21 @@ Target_x86_64::Scan::global(const General_options& options,
|
||||||
if (target->may_need_copy_reloc(gsym))
|
if (target->may_need_copy_reloc(gsym))
|
||||||
{
|
{
|
||||||
target->copy_reloc(&options, symtab, layout, object, data_shndx,
|
target->copy_reloc(&options, symtab, layout, object, data_shndx,
|
||||||
gsym, reloc);
|
output_section, gsym, reloc);
|
||||||
}
|
}
|
||||||
else if (r_type == elfcpp::R_X86_64_64
|
else if (r_type == elfcpp::R_X86_64_64
|
||||||
&& gsym->can_use_relative_reloc(false))
|
&& gsym->can_use_relative_reloc(false))
|
||||||
{
|
{
|
||||||
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
||||||
rela_dyn->add_local(object, 0, elfcpp::R_X86_64_RELATIVE,
|
rela_dyn->add_local(object, 0, elfcpp::R_X86_64_RELATIVE,
|
||||||
data_shndx,
|
output_section, data_shndx,
|
||||||
reloc.get_r_offset(), 0);
|
reloc.get_r_offset(), 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
||||||
rela_dyn->add_global(gsym, r_type, object, data_shndx,
|
rela_dyn->add_global(gsym, r_type, output_section, object,
|
||||||
reloc.get_r_offset(),
|
data_shndx, reloc.get_r_offset(),
|
||||||
reloc.get_r_addend());
|
reloc.get_r_addend());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1001,13 +1005,13 @@ Target_x86_64::Scan::global(const General_options& options,
|
||||||
if (target->may_need_copy_reloc(gsym))
|
if (target->may_need_copy_reloc(gsym))
|
||||||
{
|
{
|
||||||
target->copy_reloc(&options, symtab, layout, object, data_shndx,
|
target->copy_reloc(&options, symtab, layout, object, data_shndx,
|
||||||
gsym, reloc);
|
output_section, gsym, reloc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
||||||
rela_dyn->add_global(gsym, r_type, object, data_shndx,
|
rela_dyn->add_global(gsym, r_type, output_section, object,
|
||||||
reloc.get_r_offset(),
|
data_shndx, reloc.get_r_offset(),
|
||||||
reloc.get_r_addend());
|
reloc.get_r_addend());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue