From Cary Coutant: Fix handling of RELATIVE RELA relocs.
This commit is contained in:
parent
c68cf8ad10
commit
e8c846c359
6 changed files with 200 additions and 111 deletions
43
gold/i386.cc
43
gold/i386.cc
|
@ -811,8 +811,10 @@ 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, output_section,
|
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
|
||||||
data_shndx, reloc.get_r_offset());
|
rel_dyn->add_local_relative(object, r_sym, elfcpp::R_386_RELATIVE,
|
||||||
|
output_section, data_shndx,
|
||||||
|
reloc.get_r_offset());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -860,8 +862,11 @@ 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,
|
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
|
||||||
got, object->local_got_offset(r_sym));
|
rel_dyn->add_local_relative(object, r_sym,
|
||||||
|
elfcpp::R_386_RELATIVE,
|
||||||
|
got,
|
||||||
|
object->local_got_offset(r_sym));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -955,9 +960,12 @@ Target_i386::Scan::local(const General_options&,
|
||||||
&& parameters->output_is_shared())
|
&& parameters->output_is_shared())
|
||||||
{
|
{
|
||||||
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,
|
unsigned int r_sym
|
||||||
output_section, data_shndx,
|
= elfcpp::elf_r_sym<32>(reloc.get_r_info());
|
||||||
reloc.get_r_offset());
|
rel_dyn->add_local_relative(object, r_sym,
|
||||||
|
elfcpp::R_386_RELATIVE,
|
||||||
|
output_section, data_shndx,
|
||||||
|
reloc.get_r_offset());
|
||||||
}
|
}
|
||||||
// Create a GOT entry for the tp-relative offset.
|
// Create a GOT entry for the tp-relative offset.
|
||||||
Output_data_got<32, false>* got
|
Output_data_got<32, false>* got
|
||||||
|
@ -1070,9 +1078,9 @@ Target_i386::Scan::global(const General_options& options,
|
||||||
&& 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_global_relative(gsym, elfcpp::R_386_RELATIVE,
|
||||||
output_section, data_shndx,
|
output_section, object,
|
||||||
reloc.get_r_offset());
|
data_shndx, reloc.get_r_offset());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1136,12 +1144,8 @@ Target_i386::Scan::global(const General_options& options,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (got->add_global(gsym))
|
if (got->add_global(gsym))
|
||||||
{
|
rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE,
|
||||||
rel_dyn->add_local(object, 0, elfcpp::R_386_RELATIVE,
|
got, gsym->got_offset());
|
||||||
got, gsym->got_offset());
|
|
||||||
// Make sure we write the link-time value to the GOT.
|
|
||||||
gsym->set_needs_value_in_got();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1264,9 +1268,10 @@ Target_i386::Scan::global(const General_options& options,
|
||||||
&& parameters->output_is_shared())
|
&& parameters->output_is_shared())
|
||||||
{
|
{
|
||||||
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_global_relative(gsym, elfcpp::R_386_RELATIVE,
|
||||||
output_section, data_shndx,
|
output_section, object,
|
||||||
reloc.get_r_offset());
|
data_shndx,
|
||||||
|
reloc.get_r_offset());
|
||||||
}
|
}
|
||||||
// Create a GOT entry for the tp-relative offset.
|
// Create a GOT entry for the tp-relative offset.
|
||||||
Output_data_got<32, false>* got
|
Output_data_got<32, false>* got
|
||||||
|
|
|
@ -512,13 +512,14 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
|
||||||
Symbol* gsym,
|
Symbol* gsym,
|
||||||
unsigned int type,
|
unsigned int type,
|
||||||
Output_data* od,
|
Output_data* od,
|
||||||
Address address)
|
Address address,
|
||||||
|
bool is_relative)
|
||||||
: address_(address), local_sym_index_(GSYM_CODE), type_(type),
|
: address_(address), local_sym_index_(GSYM_CODE), type_(type),
|
||||||
shndx_(INVALID_CODE)
|
is_relative_(is_relative), shndx_(INVALID_CODE)
|
||||||
{
|
{
|
||||||
this->u1_.gsym = gsym;
|
this->u1_.gsym = gsym;
|
||||||
this->u2_.od = od;
|
this->u2_.od = od;
|
||||||
if (dynamic)
|
if (dynamic && !is_relative)
|
||||||
gsym->set_needs_dynsym_entry();
|
gsym->set_needs_dynsym_entry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -528,14 +529,15 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
|
||||||
unsigned int type,
|
unsigned int type,
|
||||||
Relobj* relobj,
|
Relobj* relobj,
|
||||||
unsigned int shndx,
|
unsigned int shndx,
|
||||||
Address address)
|
Address address,
|
||||||
|
bool is_relative)
|
||||||
: address_(address), local_sym_index_(GSYM_CODE), type_(type),
|
: address_(address), local_sym_index_(GSYM_CODE), type_(type),
|
||||||
shndx_(shndx)
|
is_relative_(is_relative), shndx_(shndx)
|
||||||
{
|
{
|
||||||
gold_assert(shndx != INVALID_CODE);
|
gold_assert(shndx != INVALID_CODE);
|
||||||
this->u1_.gsym = gsym;
|
this->u1_.gsym = gsym;
|
||||||
this->u2_.relobj = relobj;
|
this->u2_.relobj = relobj;
|
||||||
if (dynamic)
|
if (dynamic && !is_relative)
|
||||||
gsym->set_needs_dynsym_entry();
|
gsym->set_needs_dynsym_entry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,15 +549,16 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
|
||||||
unsigned int local_sym_index,
|
unsigned int local_sym_index,
|
||||||
unsigned int type,
|
unsigned int type,
|
||||||
Output_data* od,
|
Output_data* od,
|
||||||
Address address)
|
Address address,
|
||||||
|
bool is_relative)
|
||||||
: address_(address), local_sym_index_(local_sym_index), type_(type),
|
: address_(address), local_sym_index_(local_sym_index), type_(type),
|
||||||
shndx_(INVALID_CODE)
|
is_relative_(is_relative), shndx_(INVALID_CODE)
|
||||||
{
|
{
|
||||||
gold_assert(local_sym_index != GSYM_CODE
|
gold_assert(local_sym_index != GSYM_CODE
|
||||||
&& local_sym_index != INVALID_CODE);
|
&& local_sym_index != INVALID_CODE);
|
||||||
this->u1_.relobj = relobj;
|
this->u1_.relobj = relobj;
|
||||||
this->u2_.od = od;
|
this->u2_.od = od;
|
||||||
if (dynamic && local_sym_index > 0)
|
if (dynamic && !is_relative)
|
||||||
relobj->set_needs_output_dynsym_entry(local_sym_index);
|
relobj->set_needs_output_dynsym_entry(local_sym_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,16 +568,17 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
|
||||||
unsigned int local_sym_index,
|
unsigned int local_sym_index,
|
||||||
unsigned int type,
|
unsigned int type,
|
||||||
unsigned int shndx,
|
unsigned int shndx,
|
||||||
Address address)
|
Address address,
|
||||||
|
bool is_relative)
|
||||||
: address_(address), local_sym_index_(local_sym_index), type_(type),
|
: address_(address), local_sym_index_(local_sym_index), type_(type),
|
||||||
shndx_(shndx)
|
is_relative_(is_relative), shndx_(shndx)
|
||||||
{
|
{
|
||||||
gold_assert(local_sym_index != GSYM_CODE
|
gold_assert(local_sym_index != GSYM_CODE
|
||||||
&& local_sym_index != INVALID_CODE);
|
&& local_sym_index != INVALID_CODE);
|
||||||
gold_assert(shndx != INVALID_CODE);
|
gold_assert(shndx != INVALID_CODE);
|
||||||
this->u1_.relobj = relobj;
|
this->u1_.relobj = relobj;
|
||||||
this->u2_.relobj = relobj;
|
this->u2_.relobj = relobj;
|
||||||
if (dynamic && local_sym_index > 0)
|
if (dynamic && !is_relative)
|
||||||
relobj->set_needs_output_dynsym_entry(local_sym_index);
|
relobj->set_needs_output_dynsym_entry(local_sym_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,7 +591,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
|
||||||
Output_data* od,
|
Output_data* od,
|
||||||
Address address)
|
Address address)
|
||||||
: address_(address), local_sym_index_(SECTION_CODE), type_(type),
|
: address_(address), local_sym_index_(SECTION_CODE), type_(type),
|
||||||
shndx_(INVALID_CODE)
|
is_relative_(false), shndx_(INVALID_CODE)
|
||||||
{
|
{
|
||||||
this->u1_.os = os;
|
this->u1_.os = os;
|
||||||
this->u2_.od = od;
|
this->u2_.od = od;
|
||||||
|
@ -603,7 +607,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
|
||||||
unsigned int shndx,
|
unsigned int shndx,
|
||||||
Address address)
|
Address address)
|
||||||
: address_(address), local_sym_index_(SECTION_CODE), type_(type),
|
: address_(address), local_sym_index_(SECTION_CODE), type_(type),
|
||||||
shndx_(shndx)
|
is_relative_(false), shndx_(shndx)
|
||||||
{
|
{
|
||||||
gold_assert(shndx != INVALID_CODE);
|
gold_assert(shndx != INVALID_CODE);
|
||||||
this->u1_.os = os;
|
this->u1_.os = os;
|
||||||
|
@ -685,8 +689,8 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::write_rel(
|
||||||
else if (this->u2_.od != NULL)
|
else if (this->u2_.od != NULL)
|
||||||
address += this->u2_.od->address();
|
address += this->u2_.od->address();
|
||||||
wr->put_r_offset(address);
|
wr->put_r_offset(address);
|
||||||
wr->put_r_info(elfcpp::elf_r_info<size>(this->get_symbol_index(),
|
unsigned int sym_index = this->is_relative_ ? 0 : this->get_symbol_index();
|
||||||
this->type_));
|
wr->put_r_info(elfcpp::elf_r_info<size>(sym_index, this->type_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write out a Rel relocation.
|
// Write out a Rel relocation.
|
||||||
|
@ -700,6 +704,24 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::write(
|
||||||
this->write_rel(&orel);
|
this->write_rel(&orel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the value of the symbol referred to by a Rel relocation.
|
||||||
|
|
||||||
|
template<bool dynamic, int size, bool big_endian>
|
||||||
|
typename elfcpp::Elf_types<size>::Elf_Addr
|
||||||
|
Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::symbol_value() const
|
||||||
|
{
|
||||||
|
if (this->local_sym_index_ == GSYM_CODE)
|
||||||
|
{
|
||||||
|
const Sized_symbol<size>* sym;
|
||||||
|
sym = static_cast<const Sized_symbol<size>*>(this->u1_.gsym);
|
||||||
|
return sym->value();
|
||||||
|
}
|
||||||
|
gold_assert(this->local_sym_index_ != SECTION_CODE
|
||||||
|
&& this->local_sym_index_ != INVALID_CODE);
|
||||||
|
const Sized_relobj<size, big_endian>* relobj = this->u1_.relobj;
|
||||||
|
return relobj->local_symbol_value(this->local_sym_index_);
|
||||||
|
}
|
||||||
|
|
||||||
// Write out a Rela relocation.
|
// Write out a Rela relocation.
|
||||||
|
|
||||||
template<bool dynamic, int size, bool big_endian>
|
template<bool dynamic, int size, bool big_endian>
|
||||||
|
@ -709,7 +731,10 @@ Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>::write(
|
||||||
{
|
{
|
||||||
elfcpp::Rela_write<size, big_endian> orel(pov);
|
elfcpp::Rela_write<size, big_endian> orel(pov);
|
||||||
this->rel_.write_rel(&orel);
|
this->rel_.write_rel(&orel);
|
||||||
orel.put_r_addend(this->addend_);
|
Addend addend = this->addend_;
|
||||||
|
if (rel_.is_relative())
|
||||||
|
addend += rel_.symbol_value();
|
||||||
|
orel.put_r_addend(addend);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output_data_reloc_base methods.
|
// Output_data_reloc_base methods.
|
||||||
|
@ -775,24 +800,16 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
|
||||||
{
|
{
|
||||||
case GSYM_CODE:
|
case GSYM_CODE:
|
||||||
{
|
{
|
||||||
|
// If the symbol is resolved locally, we need to write out the
|
||||||
|
// link-time value, which will be relocated dynamically by a
|
||||||
|
// RELATIVE relocation.
|
||||||
Symbol* gsym = this->u_.gsym;
|
Symbol* gsym = this->u_.gsym;
|
||||||
|
Sized_symbol<size>* sgsym;
|
||||||
// If the symbol is resolved locally, we need to write out its
|
// This cast is a bit ugly. We don't want to put a
|
||||||
// value. Otherwise we just write zero. The target code is
|
// virtual method in Symbol, because we want Symbol to be
|
||||||
// responsible for creating a relocation entry to fill in the
|
// as small as possible.
|
||||||
// value at runtime. For non-preemptible symbols in a shared
|
sgsym = static_cast<Sized_symbol<size>*>(gsym);
|
||||||
// library, the target will need to record whether or not the
|
val = sgsym->value();
|
||||||
// value should be written (e.g., it may use a RELATIVE
|
|
||||||
// relocation type).
|
|
||||||
if (gsym->final_value_is_known() || gsym->needs_value_in_got())
|
|
||||||
{
|
|
||||||
Sized_symbol<size>* sgsym;
|
|
||||||
// This cast is a bit ugly. We don't want to put a
|
|
||||||
// virtual method in Symbol, because we want Symbol to be
|
|
||||||
// as small as possible.
|
|
||||||
sgsym = static_cast<Sized_symbol<size>*>(gsym);
|
|
||||||
val = sgsym->value();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
135
gold/output.h
135
gold/output.h
|
@ -703,20 +703,20 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
||||||
// A reloc against a global symbol.
|
// A reloc against a global symbol.
|
||||||
|
|
||||||
Output_reloc(Symbol* gsym, unsigned int type, Output_data* od,
|
Output_reloc(Symbol* gsym, unsigned int type, Output_data* od,
|
||||||
Address address);
|
Address address, bool is_relative);
|
||||||
|
|
||||||
Output_reloc(Symbol* gsym, unsigned int type, Relobj* relobj,
|
Output_reloc(Symbol* gsym, unsigned int type, Relobj* relobj,
|
||||||
unsigned int shndx, Address address);
|
unsigned int shndx, Address address, bool is_relative);
|
||||||
|
|
||||||
// A reloc against a local symbol.
|
// A reloc against a local symbol.
|
||||||
|
|
||||||
Output_reloc(Sized_relobj<size, big_endian>* relobj,
|
Output_reloc(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, bool is_relative);
|
||||||
|
|
||||||
Output_reloc(Sized_relobj<size, big_endian>* relobj,
|
Output_reloc(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);
|
unsigned int shndx, Address address, bool is_relative);
|
||||||
|
|
||||||
// A reloc against the STT_SECTION symbol of an output section.
|
// A reloc against the STT_SECTION symbol of an output section.
|
||||||
|
|
||||||
|
@ -726,6 +726,16 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
||||||
Output_reloc(Output_section* os, unsigned int type, Relobj* relobj,
|
Output_reloc(Output_section* os, unsigned int type, Relobj* relobj,
|
||||||
unsigned int shndx, Address address);
|
unsigned int shndx, Address address);
|
||||||
|
|
||||||
|
// Return TRUE if this is a RELATIVE relocation.
|
||||||
|
bool
|
||||||
|
is_relative() const
|
||||||
|
{ return this->is_relative_; }
|
||||||
|
|
||||||
|
// Get the value of the symbol referred to by a Rel relocation.
|
||||||
|
|
||||||
|
Address
|
||||||
|
symbol_value() const;
|
||||||
|
|
||||||
// Write the reloc entry to an output view.
|
// Write the reloc entry to an output view.
|
||||||
void
|
void
|
||||||
write(unsigned char* pov) const;
|
write(unsigned char* pov) const;
|
||||||
|
@ -780,7 +790,9 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
||||||
// for a global symbol, or INVALID_CODE for an uninitialized value.
|
// for a global symbol, or INVALID_CODE for an uninitialized value.
|
||||||
unsigned int local_sym_index_;
|
unsigned int local_sym_index_;
|
||||||
// The reloc type--a processor specific code.
|
// The reloc type--a processor specific code.
|
||||||
unsigned int type_;
|
unsigned int type_ : 31;
|
||||||
|
// True if the relocation is a RELATIVE relocation.
|
||||||
|
bool is_relative_ : 1;
|
||||||
// If the reloc address is an input section in an object, the
|
// If the reloc address is an input section in an object, the
|
||||||
// section index. This is INVALID_CODE if the reloc address is
|
// section index. This is INVALID_CODE if the reloc address is
|
||||||
// specified in some other way.
|
// specified in some other way.
|
||||||
|
@ -805,31 +817,31 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
|
||||||
// A reloc against a global symbol.
|
// A reloc against a global symbol.
|
||||||
|
|
||||||
Output_reloc(Symbol* gsym, unsigned int type, Output_data* od,
|
Output_reloc(Symbol* gsym, unsigned int type, Output_data* od,
|
||||||
Address address, Addend addend)
|
Address address, Addend addend, bool is_relative)
|
||||||
: rel_(gsym, type, od, address), addend_(addend)
|
: rel_(gsym, type, od, address, is_relative), addend_(addend)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Output_reloc(Symbol* gsym, unsigned int type, Relobj* relobj,
|
Output_reloc(Symbol* gsym, unsigned int type, Relobj* relobj,
|
||||||
unsigned int shndx, Address address, Addend addend)
|
unsigned int shndx, Address address, Addend addend,
|
||||||
: rel_(gsym, type, relobj, shndx, address), addend_(addend)
|
bool is_relative)
|
||||||
|
: rel_(gsym, type, relobj, shndx, address, is_relative), addend_(addend)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
// A reloc against a local symbol.
|
// A reloc against a local symbol.
|
||||||
|
|
||||||
Output_reloc(Sized_relobj<size, big_endian>* relobj,
|
Output_reloc(Sized_relobj<size, big_endian>* relobj,
|
||||||
unsigned int local_sym_index,
|
unsigned int local_sym_index, unsigned int type,
|
||||||
unsigned int type, Output_data* od, Address address,
|
Output_data* od, Address address,
|
||||||
Addend addend)
|
Addend addend, bool is_relative)
|
||||||
: rel_(relobj, local_sym_index, type, od, address), addend_(addend)
|
: rel_(relobj, local_sym_index, type, od, address, is_relative),
|
||||||
|
addend_(addend)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Output_reloc(Sized_relobj<size, big_endian>* relobj,
|
Output_reloc(Sized_relobj<size, big_endian>* relobj,
|
||||||
unsigned int local_sym_index,
|
unsigned int local_sym_index, unsigned int type,
|
||||||
unsigned int type,
|
unsigned int shndx, Address address,
|
||||||
unsigned int shndx,
|
Addend addend, bool is_relative)
|
||||||
Address address,
|
: rel_(relobj, local_sym_index, type, shndx, address, is_relative),
|
||||||
Addend addend)
|
|
||||||
: rel_(relobj, local_sym_index, type, shndx, address),
|
|
||||||
addend_(addend)
|
addend_(addend)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
@ -928,12 +940,27 @@ 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(od, Output_reloc_type(gsym, type, od, address)); }
|
{ this->add(od, Output_reloc_type(gsym, type, od, address, false)); }
|
||||||
|
|
||||||
void
|
void
|
||||||
add_global(Symbol* gsym, unsigned int type, Output_data* od, 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(od, Output_reloc_type(gsym, type, relobj, shndx, address)); }
|
{ this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
|
||||||
|
false)); }
|
||||||
|
|
||||||
|
// Add a RELATIVE reloc against a global symbol. The final relocation
|
||||||
|
// will not reference the symbol.
|
||||||
|
|
||||||
|
void
|
||||||
|
add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
|
||||||
|
Address address)
|
||||||
|
{ this->add(od, Output_reloc_type(gsym, type, od, address, true)); }
|
||||||
|
|
||||||
|
void
|
||||||
|
add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
|
||||||
|
Relobj* relobj, unsigned int shndx, Address address)
|
||||||
|
{ this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
|
||||||
|
true)); }
|
||||||
|
|
||||||
// Add a reloc against a local symbol.
|
// Add a reloc against a local symbol.
|
||||||
|
|
||||||
|
@ -942,15 +969,30 @@ class Output_data_reloc<elfcpp::SHT_REL, 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)
|
Output_data* od, Address address)
|
||||||
{ this->add(od, Output_reloc_type(relobj, local_sym_index, type, od,
|
{ this->add(od, Output_reloc_type(relobj, local_sym_index, type, od,
|
||||||
address)); }
|
address, false)); }
|
||||||
|
|
||||||
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,
|
||||||
Output_data* od, unsigned int shndx, Address address)
|
Output_data* od, unsigned int shndx, Address address)
|
||||||
{ this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
|
{ this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
|
||||||
address)); }
|
address, false)); }
|
||||||
|
|
||||||
|
// Add a RELATIVE reloc against a local symbol.
|
||||||
|
|
||||||
|
void
|
||||||
|
add_local_relative(Sized_relobj<size, big_endian>* relobj,
|
||||||
|
unsigned int local_sym_index, unsigned int type,
|
||||||
|
Output_data* od, Address address)
|
||||||
|
{ this->add(od, Output_reloc_type(relobj, local_sym_index, type, od,
|
||||||
|
address, true)); }
|
||||||
|
|
||||||
|
void
|
||||||
|
add_local_relative(Sized_relobj<size, big_endian>* relobj,
|
||||||
|
unsigned int local_sym_index, unsigned int type,
|
||||||
|
Output_data* od, unsigned int shndx, Address address)
|
||||||
|
{ this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
|
||||||
|
address, true)); }
|
||||||
|
|
||||||
// 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
|
// OS is the Output_section that the relocation refers to; OD is
|
||||||
|
@ -991,14 +1033,32 @@ 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(od, Output_reloc_type(gsym, type, od, address, addend)); }
|
{ this->add(od, Output_reloc_type(gsym, type, od, address, addend,
|
||||||
|
false)); }
|
||||||
|
|
||||||
void
|
void
|
||||||
add_global(Symbol* gsym, unsigned int type, Output_data* od, Relobj* relobj,
|
add_global(Symbol* gsym, unsigned int type, Output_data* od, Relobj* relobj,
|
||||||
unsigned int shndx, Address address,
|
unsigned int shndx, Address address,
|
||||||
Addend addend)
|
Addend addend)
|
||||||
{ this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
|
{ this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
|
||||||
addend)); }
|
addend, false)); }
|
||||||
|
|
||||||
|
// Add a RELATIVE reloc against a global symbol. The final output
|
||||||
|
// relocation will not reference the symbol, but we must keep the symbol
|
||||||
|
// information long enough to set the addend of the relocation correctly
|
||||||
|
// when it is written.
|
||||||
|
|
||||||
|
void
|
||||||
|
add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
|
||||||
|
Address address, Addend addend)
|
||||||
|
{ this->add(od, Output_reloc_type(gsym, type, od, address, addend, true)); }
|
||||||
|
|
||||||
|
void
|
||||||
|
add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
|
||||||
|
Relobj* relobj, unsigned int shndx, Address address,
|
||||||
|
Addend addend)
|
||||||
|
{ this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
|
||||||
|
addend, true)); }
|
||||||
|
|
||||||
// Add a reloc against a local symbol.
|
// Add a reloc against a local symbol.
|
||||||
|
|
||||||
|
@ -1008,7 +1068,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
|
||||||
Output_data* od, Address address, Addend addend)
|
Output_data* od, Address address, Addend addend)
|
||||||
{
|
{
|
||||||
this->add(od, 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, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1018,7 +1078,28 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
|
||||||
Addend addend)
|
Addend addend)
|
||||||
{
|
{
|
||||||
this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
|
this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
|
||||||
address, addend));
|
address, addend, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a RELATIVE reloc against a local symbol.
|
||||||
|
|
||||||
|
void
|
||||||
|
add_local_relative(Sized_relobj<size, big_endian>* relobj,
|
||||||
|
unsigned int local_sym_index, unsigned int type,
|
||||||
|
Output_data* od, Address address, Addend addend)
|
||||||
|
{
|
||||||
|
this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, address,
|
||||||
|
addend, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
add_local_relative(Sized_relobj<size, big_endian>* relobj,
|
||||||
|
unsigned int local_sym_index, unsigned int type,
|
||||||
|
Output_data* od, unsigned int shndx, Address address,
|
||||||
|
Addend addend)
|
||||||
|
{
|
||||||
|
this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
|
||||||
|
address, addend, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
// A reloc against the STT_SECTION symbol of an output section.
|
// A reloc against the STT_SECTION symbol of an output section.
|
||||||
|
|
|
@ -70,7 +70,6 @@ Symbol::init_fields(const char* name, const char* version,
|
||||||
this->has_plt_offset_ = false;
|
this->has_plt_offset_ = false;
|
||||||
this->has_warning_ = false;
|
this->has_warning_ = false;
|
||||||
this->is_copied_from_dynobj_ = false;
|
this->is_copied_from_dynobj_ = false;
|
||||||
this->needs_value_in_got_ = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the demangled version of the symbol's name, but only
|
// Return the demangled version of the symbol's name, but only
|
||||||
|
|
|
@ -541,19 +541,6 @@ class Symbol
|
||||||
set_is_copied_from_dynobj()
|
set_is_copied_from_dynobj()
|
||||||
{ this->is_copied_from_dynobj_ = true; }
|
{ this->is_copied_from_dynobj_ = true; }
|
||||||
|
|
||||||
// Mark this symbol as needing its value written to the GOT even when
|
|
||||||
// the value is subject to dynamic relocation (e.g., when the target
|
|
||||||
// uses a RELATIVE relocation for the GOT entry).
|
|
||||||
void
|
|
||||||
set_needs_value_in_got()
|
|
||||||
{ this->needs_value_in_got_ = true; }
|
|
||||||
|
|
||||||
// Return whether this symbol needs its value written to the GOT even
|
|
||||||
// when the value is subject to dynamic relocation.
|
|
||||||
bool
|
|
||||||
needs_value_in_got() const
|
|
||||||
{ return this->needs_value_in_got_; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Instances of this class should always be created at a specific
|
// Instances of this class should always be created at a specific
|
||||||
// size.
|
// size.
|
||||||
|
@ -730,9 +717,6 @@ class Symbol
|
||||||
// True if we are using a COPY reloc for this symbol, so that the
|
// True if we are using a COPY reloc for this symbol, so that the
|
||||||
// real definition lives in a dynamic object.
|
// real definition lives in a dynamic object.
|
||||||
bool is_copied_from_dynobj_ : 1;
|
bool is_copied_from_dynobj_ : 1;
|
||||||
// True if the static value should be written to the GOT even
|
|
||||||
// when the final value is subject to dynamic relocation.
|
|
||||||
bool needs_value_in_got_ : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// The parts of a symbol which are size specific. Using a template
|
// The parts of a symbol which are size specific. Using a template
|
||||||
|
|
|
@ -765,10 +765,13 @@ Target_x86_64::Scan::local(const General_options&,
|
||||||
// relocate it easily.
|
// relocate it easily.
|
||||||
if (parameters->output_is_position_independent())
|
if (parameters->output_is_position_independent())
|
||||||
{
|
{
|
||||||
|
unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
|
||||||
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_relative(object, r_sym,
|
||||||
output_section, data_shndx,
|
elfcpp::R_X86_64_RELATIVE,
|
||||||
reloc.get_r_offset(), 0);
|
output_section, data_shndx,
|
||||||
|
reloc.get_r_offset(),
|
||||||
|
reloc.get_r_addend());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -831,8 +834,10 @@ 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);
|
||||||
// R_X86_64_RELATIVE assumes a 64-bit relocation.
|
// R_X86_64_RELATIVE assumes a 64-bit relocation.
|
||||||
if (r_type != elfcpp::R_X86_64_GOT32)
|
if (r_type != elfcpp::R_X86_64_GOT32)
|
||||||
rela_dyn->add_local(object, 0, elfcpp::R_X86_64_RELATIVE,
|
rela_dyn->add_local_relative(object, r_sym,
|
||||||
got, object->local_got_offset(r_sym), 0);
|
elfcpp::R_X86_64_RELATIVE, got,
|
||||||
|
object->local_got_offset(r_sym),
|
||||||
|
0);
|
||||||
else
|
else
|
||||||
rela_dyn->add_local(object, r_sym, r_type,
|
rela_dyn->add_local(object, r_sym, r_type,
|
||||||
got, object->local_got_offset(r_sym), 0);
|
got, object->local_got_offset(r_sym), 0);
|
||||||
|
@ -1012,9 +1017,10 @@ Target_x86_64::Scan::global(const General_options& options,
|
||||||
&& 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_global_relative(gsym, elfcpp::R_X86_64_RELATIVE,
|
||||||
output_section, data_shndx,
|
output_section, object,
|
||||||
reloc.get_r_offset(), 0);
|
data_shndx, reloc.get_r_offset(),
|
||||||
|
reloc.get_r_addend());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1076,12 +1082,9 @@ Target_x86_64::Scan::global(const General_options& options,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (got->add_global(gsym))
|
if (got->add_global(gsym))
|
||||||
{
|
rela_dyn->add_global_relative(gsym,
|
||||||
rela_dyn->add_local(object, 0, elfcpp::R_X86_64_RELATIVE,
|
elfcpp::R_X86_64_RELATIVE,
|
||||||
got, gsym->got_offset(), 0);
|
got, gsym->got_offset(), 0);
|
||||||
// Make sure we write the link-time value to the GOT.
|
|
||||||
gsym->set_needs_value_in_got();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// For GOTPLT64, we also need a PLT entry (but only if the
|
// For GOTPLT64, we also need a PLT entry (but only if the
|
||||||
|
|
Loading…
Reference in a new issue