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
35
gold/i386.cc
35
gold/i386.cc
|
@ -811,8 +811,10 @@ Target_i386::Scan::local(const General_options&,
|
|||
if (parameters->output_is_position_independent())
|
||||
{
|
||||
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
|
||||
rel_dyn->add_local(object, 0, elfcpp::R_386_RELATIVE, output_section,
|
||||
data_shndx, reloc.get_r_offset());
|
||||
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
|
||||
rel_dyn->add_local_relative(object, r_sym, elfcpp::R_386_RELATIVE,
|
||||
output_section, data_shndx,
|
||||
reloc.get_r_offset());
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -860,8 +862,11 @@ Target_i386::Scan::local(const General_options&,
|
|||
if (parameters->output_is_position_independent())
|
||||
{
|
||||
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
|
||||
rel_dyn->add_local(object, 0, elfcpp::R_386_RELATIVE,
|
||||
got, object->local_got_offset(r_sym));
|
||||
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
|
||||
rel_dyn->add_local_relative(object, r_sym,
|
||||
elfcpp::R_386_RELATIVE,
|
||||
got,
|
||||
object->local_got_offset(r_sym));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -955,7 +960,10 @@ Target_i386::Scan::local(const General_options&,
|
|||
&& parameters->output_is_shared())
|
||||
{
|
||||
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());
|
||||
rel_dyn->add_local_relative(object, r_sym,
|
||||
elfcpp::R_386_RELATIVE,
|
||||
output_section, data_shndx,
|
||||
reloc.get_r_offset());
|
||||
}
|
||||
|
@ -1070,9 +1078,9 @@ Target_i386::Scan::global(const General_options& options,
|
|||
&& gsym->can_use_relative_reloc(false))
|
||||
{
|
||||
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
|
||||
rel_dyn->add_local(object, 0, elfcpp::R_386_RELATIVE,
|
||||
output_section, data_shndx,
|
||||
reloc.get_r_offset());
|
||||
rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE,
|
||||
output_section, object,
|
||||
data_shndx, reloc.get_r_offset());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1136,12 +1144,8 @@ Target_i386::Scan::global(const General_options& options,
|
|||
else
|
||||
{
|
||||
if (got->add_global(gsym))
|
||||
{
|
||||
rel_dyn->add_local(object, 0, elfcpp::R_386_RELATIVE,
|
||||
rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE,
|
||||
got, gsym->got_offset());
|
||||
// Make sure we write the link-time value to the GOT.
|
||||
gsym->set_needs_value_in_got();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1264,8 +1268,9 @@ Target_i386::Scan::global(const General_options& options,
|
|||
&& parameters->output_is_shared())
|
||||
{
|
||||
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
|
||||
rel_dyn->add_local(object, 0, elfcpp::R_386_RELATIVE,
|
||||
output_section, data_shndx,
|
||||
rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE,
|
||||
output_section, object,
|
||||
data_shndx,
|
||||
reloc.get_r_offset());
|
||||
}
|
||||
// Create a GOT entry for the tp-relative offset.
|
||||
|
|
|
@ -512,13 +512,14 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
|
|||
Symbol* gsym,
|
||||
unsigned int type,
|
||||
Output_data* od,
|
||||
Address address)
|
||||
Address address,
|
||||
bool is_relative)
|
||||
: address_(address), local_sym_index_(GSYM_CODE), type_(type),
|
||||
shndx_(INVALID_CODE)
|
||||
is_relative_(is_relative), shndx_(INVALID_CODE)
|
||||
{
|
||||
this->u1_.gsym = gsym;
|
||||
this->u2_.od = od;
|
||||
if (dynamic)
|
||||
if (dynamic && !is_relative)
|
||||
gsym->set_needs_dynsym_entry();
|
||||
}
|
||||
|
||||
|
@ -528,14 +529,15 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
|
|||
unsigned int type,
|
||||
Relobj* relobj,
|
||||
unsigned int shndx,
|
||||
Address address)
|
||||
Address address,
|
||||
bool is_relative)
|
||||
: address_(address), local_sym_index_(GSYM_CODE), type_(type),
|
||||
shndx_(shndx)
|
||||
is_relative_(is_relative), shndx_(shndx)
|
||||
{
|
||||
gold_assert(shndx != INVALID_CODE);
|
||||
this->u1_.gsym = gsym;
|
||||
this->u2_.relobj = relobj;
|
||||
if (dynamic)
|
||||
if (dynamic && !is_relative)
|
||||
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 type,
|
||||
Output_data* od,
|
||||
Address address)
|
||||
Address address,
|
||||
bool is_relative)
|
||||
: 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
|
||||
&& local_sym_index != INVALID_CODE);
|
||||
this->u1_.relobj = relobj;
|
||||
this->u2_.od = od;
|
||||
if (dynamic && local_sym_index > 0)
|
||||
if (dynamic && !is_relative)
|
||||
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 type,
|
||||
unsigned int shndx,
|
||||
Address address)
|
||||
Address address,
|
||||
bool is_relative)
|
||||
: 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
|
||||
&& local_sym_index != INVALID_CODE);
|
||||
gold_assert(shndx != INVALID_CODE);
|
||||
this->u1_.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);
|
||||
}
|
||||
|
||||
|
@ -587,7 +591,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
|
|||
Output_data* od,
|
||||
Address address)
|
||||
: address_(address), local_sym_index_(SECTION_CODE), type_(type),
|
||||
shndx_(INVALID_CODE)
|
||||
is_relative_(false), shndx_(INVALID_CODE)
|
||||
{
|
||||
this->u1_.os = os;
|
||||
this->u2_.od = od;
|
||||
|
@ -603,7 +607,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
|
|||
unsigned int shndx,
|
||||
Address address)
|
||||
: address_(address), local_sym_index_(SECTION_CODE), type_(type),
|
||||
shndx_(shndx)
|
||||
is_relative_(false), shndx_(shndx)
|
||||
{
|
||||
gold_assert(shndx != INVALID_CODE);
|
||||
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)
|
||||
address += this->u2_.od->address();
|
||||
wr->put_r_offset(address);
|
||||
wr->put_r_info(elfcpp::elf_r_info<size>(this->get_symbol_index(),
|
||||
this->type_));
|
||||
unsigned int sym_index = this->is_relative_ ? 0 : this->get_symbol_index();
|
||||
wr->put_r_info(elfcpp::elf_r_info<size>(sym_index, this->type_));
|
||||
}
|
||||
|
||||
// Write out a Rel relocation.
|
||||
|
@ -700,6 +704,24 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::write(
|
|||
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.
|
||||
|
||||
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);
|
||||
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.
|
||||
|
@ -775,17 +800,10 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
|
|||
{
|
||||
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;
|
||||
|
||||
// If the symbol is resolved locally, we need to write out its
|
||||
// value. Otherwise we just write zero. The target code is
|
||||
// responsible for creating a relocation entry to fill in the
|
||||
// value at runtime. For non-preemptible symbols in a shared
|
||||
// library, the target will need to record whether or not the
|
||||
// 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
|
||||
|
@ -793,7 +811,6 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
|
|||
sgsym = static_cast<Sized_symbol<size>*>(gsym);
|
||||
val = sgsym->value();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CONSTANT_CODE:
|
||||
|
|
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.
|
||||
|
||||
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,
|
||||
unsigned int shndx, Address address);
|
||||
unsigned int shndx, Address address, bool is_relative);
|
||||
|
||||
// A reloc against a local symbol.
|
||||
|
||||
Output_reloc(Sized_relobj<size, big_endian>* relobj,
|
||||
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,
|
||||
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.
|
||||
|
||||
|
@ -726,6 +726,16 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
|||
Output_reloc(Output_section* os, unsigned int type, Relobj* relobj,
|
||||
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.
|
||||
void
|
||||
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.
|
||||
unsigned int local_sym_index_;
|
||||
// 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
|
||||
// section index. This is INVALID_CODE if the reloc address is
|
||||
// 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.
|
||||
|
||||
Output_reloc(Symbol* gsym, unsigned int type, Output_data* od,
|
||||
Address address, Addend addend)
|
||||
: rel_(gsym, type, od, address), addend_(addend)
|
||||
Address address, Addend addend, bool is_relative)
|
||||
: rel_(gsym, type, od, address, is_relative), addend_(addend)
|
||||
{ }
|
||||
|
||||
Output_reloc(Symbol* gsym, unsigned int type, Relobj* relobj,
|
||||
unsigned int shndx, Address address, Addend addend)
|
||||
: rel_(gsym, type, relobj, shndx, address), addend_(addend)
|
||||
unsigned int shndx, Address address, Addend addend,
|
||||
bool is_relative)
|
||||
: rel_(gsym, type, relobj, shndx, address, is_relative), addend_(addend)
|
||||
{ }
|
||||
|
||||
// A reloc against a local symbol.
|
||||
|
||||
Output_reloc(Sized_relobj<size, big_endian>* relobj,
|
||||
unsigned int local_sym_index,
|
||||
unsigned int type, Output_data* od, Address address,
|
||||
Addend addend)
|
||||
: rel_(relobj, local_sym_index, type, od, address), addend_(addend)
|
||||
unsigned int local_sym_index, unsigned int type,
|
||||
Output_data* od, Address address,
|
||||
Addend addend, bool is_relative)
|
||||
: rel_(relobj, local_sym_index, type, od, address, is_relative),
|
||||
addend_(addend)
|
||||
{ }
|
||||
|
||||
Output_reloc(Sized_relobj<size, big_endian>* relobj,
|
||||
unsigned int local_sym_index,
|
||||
unsigned int type,
|
||||
unsigned int shndx,
|
||||
Address address,
|
||||
Addend addend)
|
||||
: rel_(relobj, local_sym_index, type, shndx, address),
|
||||
unsigned int local_sym_index, unsigned int type,
|
||||
unsigned int shndx, Address address,
|
||||
Addend addend, bool is_relative)
|
||||
: rel_(relobj, local_sym_index, type, shndx, address, is_relative),
|
||||
addend_(addend)
|
||||
{ }
|
||||
|
||||
|
@ -928,12 +940,27 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
|||
|
||||
void
|
||||
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
|
||||
add_global(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)); }
|
||||
{ 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.
|
||||
|
||||
|
@ -942,15 +969,30 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
|||
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)); }
|
||||
address, false)); }
|
||||
|
||||
void
|
||||
add_local(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)); }
|
||||
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.
|
||||
// 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
|
||||
add_global(Symbol* gsym, unsigned int type, Output_data* od,
|
||||
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
|
||||
add_global(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)); }
|
||||
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.
|
||||
|
||||
|
@ -1008,7 +1068,7 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
|
|||
Output_data* od, Address address, Addend addend)
|
||||
{
|
||||
this->add(od, Output_reloc_type(relobj, local_sym_index, type, od, address,
|
||||
addend));
|
||||
addend, false));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1018,7 +1078,28 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
|
|||
Addend addend)
|
||||
{
|
||||
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.
|
||||
|
|
|
@ -70,7 +70,6 @@ Symbol::init_fields(const char* name, const char* version,
|
|||
this->has_plt_offset_ = false;
|
||||
this->has_warning_ = false;
|
||||
this->is_copied_from_dynobj_ = false;
|
||||
this->needs_value_in_got_ = false;
|
||||
}
|
||||
|
||||
// Return the demangled version of the symbol's name, but only
|
||||
|
|
|
@ -541,19 +541,6 @@ class Symbol
|
|||
set_is_copied_from_dynobj()
|
||||
{ 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:
|
||||
// Instances of this class should always be created at a specific
|
||||
// size.
|
||||
|
@ -730,9 +717,6 @@ class Symbol
|
|||
// True if we are using a COPY reloc for this symbol, so that the
|
||||
// real definition lives in a dynamic object.
|
||||
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
|
||||
|
|
|
@ -765,10 +765,13 @@ Target_x86_64::Scan::local(const General_options&,
|
|||
// relocate it easily.
|
||||
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);
|
||||
rela_dyn->add_local(object, 0, elfcpp::R_X86_64_RELATIVE,
|
||||
rela_dyn->add_local_relative(object, r_sym,
|
||||
elfcpp::R_X86_64_RELATIVE,
|
||||
output_section, data_shndx,
|
||||
reloc.get_r_offset(), 0);
|
||||
reloc.get_r_offset(),
|
||||
reloc.get_r_addend());
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -831,8 +834,10 @@ Target_x86_64::Scan::local(const General_options&,
|
|||
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
||||
// R_X86_64_RELATIVE assumes a 64-bit relocation.
|
||||
if (r_type != elfcpp::R_X86_64_GOT32)
|
||||
rela_dyn->add_local(object, 0, elfcpp::R_X86_64_RELATIVE,
|
||||
got, object->local_got_offset(r_sym), 0);
|
||||
rela_dyn->add_local_relative(object, r_sym,
|
||||
elfcpp::R_X86_64_RELATIVE, got,
|
||||
object->local_got_offset(r_sym),
|
||||
0);
|
||||
else
|
||||
rela_dyn->add_local(object, r_sym, r_type,
|
||||
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))
|
||||
{
|
||||
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
||||
rela_dyn->add_local(object, 0, elfcpp::R_X86_64_RELATIVE,
|
||||
output_section, data_shndx,
|
||||
reloc.get_r_offset(), 0);
|
||||
rela_dyn->add_global_relative(gsym, elfcpp::R_X86_64_RELATIVE,
|
||||
output_section, object,
|
||||
data_shndx, reloc.get_r_offset(),
|
||||
reloc.get_r_addend());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1076,12 +1082,9 @@ Target_x86_64::Scan::global(const General_options& options,
|
|||
else
|
||||
{
|
||||
if (got->add_global(gsym))
|
||||
{
|
||||
rela_dyn->add_local(object, 0, elfcpp::R_X86_64_RELATIVE,
|
||||
rela_dyn->add_global_relative(gsym,
|
||||
elfcpp::R_X86_64_RELATIVE,
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue