mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 18:14:13 +08:00
Support dynamic relocations against local section symbols.
This commit is contained in:
parent
709d67f15a
commit
dceae3c154
17
gold/i386.cc
17
gold/i386.cc
@ -898,9 +898,19 @@ Target_i386::Scan::local(const General_options&,
|
||||
if (parameters->output_is_position_independent())
|
||||
{
|
||||
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
|
||||
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
|
||||
rel_dyn->add_local(object, r_sym, r_type, output_section, data_shndx,
|
||||
reloc.get_r_offset());
|
||||
if (lsym.get_st_type() != elfcpp::STT_SECTION)
|
||||
{
|
||||
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
|
||||
rel_dyn->add_local(object, r_sym, r_type, output_section,
|
||||
data_shndx, reloc.get_r_offset());
|
||||
}
|
||||
else
|
||||
{
|
||||
gold_assert(lsym.get_st_value() == 0);
|
||||
rel_dyn->add_local_section(object, lsym.get_st_shndx(),
|
||||
r_type, output_section,
|
||||
data_shndx, reloc.get_r_offset());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1053,6 +1063,7 @@ Target_i386::Scan::local(const General_options&,
|
||||
if (output_is_shared)
|
||||
{
|
||||
// We need to create a dynamic relocation.
|
||||
gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
|
||||
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
|
||||
unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_LE_32
|
||||
? elfcpp::R_386_TLS_TPOFF32
|
||||
|
@ -884,12 +884,14 @@ Sized_relobj<size, big_endian>::do_count_local_symbols(Stringpool* pool,
|
||||
if (shndx < shnum && mo[shndx].output_section == NULL)
|
||||
{
|
||||
lv.set_no_output_symtab_entry();
|
||||
gold_assert(!lv.needs_output_dynsym_entry());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sym.get_st_type() == elfcpp::STT_SECTION)
|
||||
{
|
||||
lv.set_no_output_symtab_entry();
|
||||
gold_assert(!lv.needs_output_dynsym_entry());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -874,6 +874,7 @@ class Symbol_value
|
||||
void
|
||||
set_needs_output_dynsym_entry()
|
||||
{
|
||||
gold_assert(!this->is_section_symbol());
|
||||
this->output_dynsym_index_ = 0;
|
||||
}
|
||||
|
||||
@ -897,7 +898,8 @@ class Symbol_value
|
||||
unsigned int
|
||||
output_dynsym_index() const
|
||||
{
|
||||
gold_assert(this->output_dynsym_index_ != 0);
|
||||
gold_assert(this->output_dynsym_index_ != 0
|
||||
&& this->output_dynsym_index_ != -1U);
|
||||
return this->output_dynsym_index_;
|
||||
}
|
||||
|
||||
@ -924,7 +926,10 @@ class Symbol_value
|
||||
// Record that this is a section symbol.
|
||||
void
|
||||
set_is_section_symbol()
|
||||
{ this->is_section_symbol_ = true; }
|
||||
{
|
||||
gold_assert(!this->needs_output_dynsym_entry());
|
||||
this->is_section_symbol_ = true;
|
||||
}
|
||||
|
||||
// Record that this is a TLS symbol.
|
||||
void
|
||||
|
143
gold/output.cc
143
gold/output.cc
@ -608,12 +608,14 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
|
||||
Address address,
|
||||
bool is_relative)
|
||||
: address_(address), local_sym_index_(GSYM_CODE), type_(type),
|
||||
is_relative_(is_relative), shndx_(INVALID_CODE)
|
||||
is_relative_(is_relative), is_section_symbol_(false), shndx_(INVALID_CODE)
|
||||
{
|
||||
// this->type_ is a bitfield; make sure TYPE fits.
|
||||
gold_assert(this->type_ == type);
|
||||
this->u1_.gsym = gsym;
|
||||
this->u2_.od = od;
|
||||
if (dynamic && !is_relative)
|
||||
gsym->set_needs_dynsym_entry();
|
||||
if (dynamic)
|
||||
this->set_needs_dynsym_index();
|
||||
}
|
||||
|
||||
template<bool dynamic, int size, bool big_endian>
|
||||
@ -625,13 +627,15 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
|
||||
Address address,
|
||||
bool is_relative)
|
||||
: address_(address), local_sym_index_(GSYM_CODE), type_(type),
|
||||
is_relative_(is_relative), shndx_(shndx)
|
||||
is_relative_(is_relative), is_section_symbol_(false), shndx_(shndx)
|
||||
{
|
||||
gold_assert(shndx != INVALID_CODE);
|
||||
// this->type_ is a bitfield; make sure TYPE fits.
|
||||
gold_assert(this->type_ == type);
|
||||
this->u1_.gsym = gsym;
|
||||
this->u2_.relobj = relobj;
|
||||
if (dynamic && !is_relative)
|
||||
gsym->set_needs_dynsym_entry();
|
||||
if (dynamic)
|
||||
this->set_needs_dynsym_index();
|
||||
}
|
||||
|
||||
// A reloc against a local symbol.
|
||||
@ -643,16 +647,20 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
|
||||
unsigned int type,
|
||||
Output_data* od,
|
||||
Address address,
|
||||
bool is_relative)
|
||||
bool is_relative,
|
||||
bool is_section_symbol)
|
||||
: address_(address), local_sym_index_(local_sym_index), type_(type),
|
||||
is_relative_(is_relative), shndx_(INVALID_CODE)
|
||||
is_relative_(is_relative), is_section_symbol_(is_section_symbol),
|
||||
shndx_(INVALID_CODE)
|
||||
{
|
||||
gold_assert(local_sym_index != GSYM_CODE
|
||||
&& local_sym_index != INVALID_CODE);
|
||||
// this->type_ is a bitfield; make sure TYPE fits.
|
||||
gold_assert(this->type_ == type);
|
||||
this->u1_.relobj = relobj;
|
||||
this->u2_.od = od;
|
||||
if (dynamic && !is_relative)
|
||||
relobj->set_needs_output_dynsym_entry(local_sym_index);
|
||||
if (dynamic)
|
||||
this->set_needs_dynsym_index();
|
||||
}
|
||||
|
||||
template<bool dynamic, int size, bool big_endian>
|
||||
@ -662,17 +670,21 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
|
||||
unsigned int type,
|
||||
unsigned int shndx,
|
||||
Address address,
|
||||
bool is_relative)
|
||||
bool is_relative,
|
||||
bool is_section_symbol)
|
||||
: address_(address), local_sym_index_(local_sym_index), type_(type),
|
||||
is_relative_(is_relative), shndx_(shndx)
|
||||
is_relative_(is_relative), is_section_symbol_(is_section_symbol),
|
||||
shndx_(shndx)
|
||||
{
|
||||
gold_assert(local_sym_index != GSYM_CODE
|
||||
&& local_sym_index != INVALID_CODE);
|
||||
gold_assert(shndx != INVALID_CODE);
|
||||
// this->type_ is a bitfield; make sure TYPE fits.
|
||||
gold_assert(this->type_ == type);
|
||||
this->u1_.relobj = relobj;
|
||||
this->u2_.relobj = relobj;
|
||||
if (dynamic && !is_relative)
|
||||
relobj->set_needs_output_dynsym_entry(local_sym_index);
|
||||
if (dynamic)
|
||||
this->set_needs_dynsym_index();
|
||||
}
|
||||
|
||||
// A reloc against the STT_SECTION symbol of an output section.
|
||||
@ -684,12 +696,16 @@ 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),
|
||||
is_relative_(false), shndx_(INVALID_CODE)
|
||||
is_relative_(false), is_section_symbol_(true), shndx_(INVALID_CODE)
|
||||
{
|
||||
// this->type_ is a bitfield; make sure TYPE fits.
|
||||
gold_assert(this->type_ == type);
|
||||
this->u1_.os = os;
|
||||
this->u2_.od = od;
|
||||
if (dynamic)
|
||||
os->set_needs_dynsym_index();
|
||||
this->set_needs_dynsym_index();
|
||||
else
|
||||
os->set_needs_symtab_index();
|
||||
}
|
||||
|
||||
template<bool dynamic, int size, bool big_endian>
|
||||
@ -700,13 +716,59 @@ 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),
|
||||
is_relative_(false), shndx_(shndx)
|
||||
is_relative_(false), is_section_symbol_(true), shndx_(shndx)
|
||||
{
|
||||
gold_assert(shndx != INVALID_CODE);
|
||||
// this->type_ is a bitfield; make sure TYPE fits.
|
||||
gold_assert(this->type_ == type);
|
||||
this->u1_.os = os;
|
||||
this->u2_.relobj = relobj;
|
||||
if (dynamic)
|
||||
os->set_needs_dynsym_index();
|
||||
this->set_needs_dynsym_index();
|
||||
else
|
||||
os->set_needs_symtab_index();
|
||||
}
|
||||
|
||||
// Record that we need a dynamic symbol index for this relocation.
|
||||
|
||||
template<bool dynamic, int size, bool big_endian>
|
||||
void
|
||||
Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::
|
||||
set_needs_dynsym_index()
|
||||
{
|
||||
if (this->is_relative_)
|
||||
return;
|
||||
switch (this->local_sym_index_)
|
||||
{
|
||||
case INVALID_CODE:
|
||||
gold_unreachable();
|
||||
|
||||
case GSYM_CODE:
|
||||
this->u1_.gsym->set_needs_dynsym_entry();
|
||||
break;
|
||||
|
||||
case SECTION_CODE:
|
||||
this->u1_.os->set_needs_dynsym_index();
|
||||
break;
|
||||
|
||||
case 0:
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
const unsigned int lsi = this->local_sym_index_;
|
||||
if (!this->is_section_symbol_)
|
||||
this->u1_.relobj->set_needs_output_dynsym_entry(lsi);
|
||||
else
|
||||
{
|
||||
section_offset_type dummy;
|
||||
Output_section* os = this->u1_.relobj->output_section(lsi, &dummy);
|
||||
gold_assert(os != NULL);
|
||||
os->set_needs_dynsym_index();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the symbol index of a relocation.
|
||||
@ -744,16 +806,47 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::get_symbol_index()
|
||||
break;
|
||||
|
||||
default:
|
||||
if (dynamic)
|
||||
index = this->u1_.relobj->dynsym_index(this->local_sym_index_);
|
||||
else
|
||||
index = this->u1_.relobj->symtab_index(this->local_sym_index_);
|
||||
{
|
||||
const unsigned int lsi = this->local_sym_index_;
|
||||
if (!this->is_section_symbol_)
|
||||
{
|
||||
if (dynamic)
|
||||
index = this->u1_.relobj->dynsym_index(lsi);
|
||||
else
|
||||
index = this->u1_.relobj->symtab_index(lsi);
|
||||
}
|
||||
else
|
||||
{
|
||||
section_offset_type dummy;
|
||||
Output_section* os = this->u1_.relobj->output_section(lsi, &dummy);
|
||||
gold_assert(os != NULL);
|
||||
if (dynamic)
|
||||
index = os->dynsym_index();
|
||||
else
|
||||
index = os->symtab_index();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
gold_assert(index != -1U);
|
||||
return index;
|
||||
}
|
||||
|
||||
// For a local section symbol, get the section offset of the input
|
||||
// section within the output section.
|
||||
|
||||
template<bool dynamic, int size, bool big_endian>
|
||||
section_offset_type
|
||||
Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::
|
||||
local_section_offset() const
|
||||
{
|
||||
const unsigned int lsi = this->local_sym_index_;
|
||||
section_offset_type offset;
|
||||
Output_section* os = this->u1_.relobj->output_section(lsi, &offset);
|
||||
gold_assert(os != NULL);
|
||||
return offset;
|
||||
}
|
||||
|
||||
// Write out the offset and info fields of a Rel or Rela relocation
|
||||
// entry.
|
||||
|
||||
@ -825,8 +918,10 @@ Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>::write(
|
||||
elfcpp::Rela_write<size, big_endian> orel(pov);
|
||||
this->rel_.write_rel(&orel);
|
||||
Addend addend = this->addend_;
|
||||
if (rel_.is_relative())
|
||||
addend += rel_.symbol_value();
|
||||
if (this->rel_.is_relative())
|
||||
addend += this->rel_.symbol_value();
|
||||
if (this->rel_.is_local_section_symbol())
|
||||
addend += this->rel_.local_section_offset();
|
||||
orel.put_r_addend(addend);
|
||||
}
|
||||
|
||||
|
173
gold/output.h
173
gold/output.h
@ -767,9 +767,9 @@ class Output_data_strtab : public Output_section_data
|
||||
// or elfcpp::SHT_RELA, and also on whether this is a dynamic
|
||||
// relocation or an ordinary relocation.
|
||||
|
||||
// A relocation can be against a global symbol, a local symbol, an
|
||||
// output section, or the undefined symbol at index 0. We represent
|
||||
// the latter by using a NULL global symbol.
|
||||
// A relocation can be against a global symbol, a local symbol, a
|
||||
// local section symbol, an output section, or the undefined symbol at
|
||||
// index 0. We represent the latter by using a NULL global symbol.
|
||||
|
||||
template<int sh_type, bool dynamic, int size, bool big_endian>
|
||||
class Output_reloc;
|
||||
@ -786,6 +786,11 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
||||
: local_sym_index_(INVALID_CODE)
|
||||
{ }
|
||||
|
||||
// We have a bunch of different constructors. They come in pairs
|
||||
// depending on how the address of the relocation is specified. It
|
||||
// can either be an offset in an Output_data or an offset in an
|
||||
// input section.
|
||||
|
||||
// A reloc against a global symbol.
|
||||
|
||||
Output_reloc(Symbol* gsym, unsigned int type, Output_data* od,
|
||||
@ -794,15 +799,17 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
||||
Output_reloc(Symbol* gsym, unsigned int type, Relobj* relobj,
|
||||
unsigned int shndx, Address address, bool is_relative);
|
||||
|
||||
// A reloc against a local symbol.
|
||||
// A reloc against a local symbol or local section symbol.
|
||||
|
||||
Output_reloc(Sized_relobj<size, big_endian>* relobj,
|
||||
unsigned int local_sym_index, unsigned int type,
|
||||
Output_data* od, Address address, bool is_relative);
|
||||
Output_data* od, Address address, bool is_relative,
|
||||
bool is_section_symbol);
|
||||
|
||||
Output_reloc(Sized_relobj<size, big_endian>* relobj,
|
||||
unsigned int local_sym_index, unsigned int type,
|
||||
unsigned int shndx, Address address, bool is_relative);
|
||||
unsigned int shndx, Address address, bool is_relative,
|
||||
bool is_section_symbol);
|
||||
|
||||
// A reloc against the STT_SECTION symbol of an output section.
|
||||
|
||||
@ -817,6 +824,21 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
||||
is_relative() const
|
||||
{ return this->is_relative_; }
|
||||
|
||||
// Return whether this is against a local section symbol.
|
||||
bool
|
||||
is_local_section_symbol() const
|
||||
{
|
||||
return (this->local_sym_index_ != GSYM_CODE
|
||||
&& this->local_sym_index_ != SECTION_CODE
|
||||
&& this->local_sym_index_ != INVALID_CODE
|
||||
&& this->is_section_symbol_);
|
||||
}
|
||||
|
||||
// For a local section symbol, return the offset of the input
|
||||
// section within the output section.
|
||||
section_offset_type
|
||||
local_section_offset() const;
|
||||
|
||||
// Get the value of the symbol referred to by a Rel relocation.
|
||||
|
||||
Address
|
||||
@ -831,8 +853,11 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
||||
void write_rel(Write_rel*) const;
|
||||
|
||||
private:
|
||||
// Return the symbol index. We can't do a double template
|
||||
// specialization, so we do a secondary template here.
|
||||
// Record that we need a dynamic symbol index.
|
||||
void
|
||||
set_needs_dynsym_index();
|
||||
|
||||
// Return the symbol index.
|
||||
unsigned int
|
||||
get_symbol_index() const;
|
||||
|
||||
@ -849,36 +874,45 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
||||
|
||||
union
|
||||
{
|
||||
// For a local symbol, the object. We will never generate a
|
||||
// relocation against a local symbol in a dynamic object; that
|
||||
// doesn't make sense. And our callers will always be
|
||||
// templatized, so we use Sized_relobj here.
|
||||
// For a local symbol or local section symbol
|
||||
// (this->local_sym_index_ >= 0), the object. We will never
|
||||
// generate a relocation against a local symbol in a dynamic
|
||||
// object; that doesn't make sense. And our callers will always
|
||||
// be templatized, so we use Sized_relobj here.
|
||||
Sized_relobj<size, big_endian>* relobj;
|
||||
// For a global symbol, the symbol. If this is NULL, it indicates
|
||||
// a relocation against the undefined 0 symbol.
|
||||
// For a global symbol (this->local_sym_index_ == GSYM_CODE, the
|
||||
// symbol. If this is NULL, it indicates a relocation against the
|
||||
// undefined 0 symbol.
|
||||
Symbol* gsym;
|
||||
// For a relocation against an output section, the output section.
|
||||
// For a relocation against an output section
|
||||
// (this->local_sym_index_ == SECTION_CODE), the output section.
|
||||
Output_section* os;
|
||||
} u1_;
|
||||
union
|
||||
{
|
||||
// If shndx_ is not INVALID CODE, the object which holds the input
|
||||
// section being used to specify the reloc address.
|
||||
// If this->shndx_ is not INVALID CODE, the object which holds the
|
||||
// input section being used to specify the reloc address.
|
||||
Relobj* relobj;
|
||||
// If shndx_ is INVALID_CODE, the output data being used to
|
||||
// If this->shndx_ is INVALID_CODE, the output data being used to
|
||||
// specify the reloc address. This may be NULL if the reloc
|
||||
// address is absolute.
|
||||
Output_data* od;
|
||||
} u2_;
|
||||
// The address offset within the input section or the Output_data.
|
||||
Address address_;
|
||||
// For a local symbol, the local symbol index. This is GSYM_CODE
|
||||
// for a global symbol, or INVALID_CODE for an uninitialized value.
|
||||
// This is GSYM_CODE for a global symbol, or SECTION_CODE for a
|
||||
// relocation against an output section, or INVALID_CODE for an
|
||||
// uninitialized value. Otherwise, for a local symbol
|
||||
// (this->is_section_symbol_ is false), the local symbol index. For
|
||||
// a local section symbol (this->is_section_symbol_ is true), the
|
||||
// section index in the input file.
|
||||
unsigned int local_sym_index_;
|
||||
// The reloc type--a processor specific code.
|
||||
unsigned int type_ : 31;
|
||||
unsigned int type_ : 30;
|
||||
// True if the relocation is a RELATIVE relocation.
|
||||
bool is_relative_ : 1;
|
||||
// True if the relocation is against a section symbol.
|
||||
bool is_section_symbol_ : 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.
|
||||
@ -918,16 +952,18 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
|
||||
Output_reloc(Sized_relobj<size, big_endian>* relobj,
|
||||
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, bool is_relative, bool is_section_symbol)
|
||||
: rel_(relobj, local_sym_index, type, od, address, is_relative,
|
||||
is_section_symbol),
|
||||
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, bool is_relative)
|
||||
: rel_(relobj, local_sym_index, type, shndx, address, is_relative),
|
||||
Addend addend, bool is_relative, bool is_section_symbol)
|
||||
: rel_(relobj, local_sym_index, type, shndx, address, is_relative,
|
||||
is_section_symbol),
|
||||
addend_(addend)
|
||||
{ }
|
||||
|
||||
@ -1010,7 +1046,7 @@ template<bool dynamic, int size, bool big_endian>
|
||||
class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
||||
: public Output_data_reloc_base<elfcpp::SHT_REL, dynamic, size, big_endian>
|
||||
{
|
||||
private:
|
||||
private:
|
||||
typedef Output_data_reloc_base<elfcpp::SHT_REL, dynamic, size,
|
||||
big_endian> Base;
|
||||
|
||||
@ -1045,8 +1081,10 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
||||
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)); }
|
||||
{
|
||||
this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
|
||||
true));
|
||||
}
|
||||
|
||||
// Add a reloc against a local symbol.
|
||||
|
||||
@ -1054,15 +1092,19 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
||||
add_local(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, false)); }
|
||||
{
|
||||
this->add(od, Output_reloc_type(relobj, local_sym_index, type, od,
|
||||
address, false, 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, false)); }
|
||||
{
|
||||
this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
|
||||
address, false, false));
|
||||
}
|
||||
|
||||
// Add a RELATIVE reloc against a local symbol.
|
||||
|
||||
@ -1070,15 +1112,41 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
|
||||
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)); }
|
||||
{
|
||||
this->add(od, Output_reloc_type(relobj, local_sym_index, type, od,
|
||||
address, true, false));
|
||||
}
|
||||
|
||||
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)); }
|
||||
{
|
||||
this->add(od, Output_reloc_type(relobj, local_sym_index, type, shndx,
|
||||
address, true, false));
|
||||
}
|
||||
|
||||
// Add a reloc against a local section symbol. This will be
|
||||
// converted into a reloc against the STT_SECTION symbol of the
|
||||
// output section.
|
||||
|
||||
void
|
||||
add_local_section(Sized_relobj<size, big_endian>* relobj,
|
||||
unsigned int input_shndx, unsigned int type,
|
||||
Output_data* od, Address address)
|
||||
{
|
||||
this->add(od, Output_reloc_type(relobj, input_shndx, type, od,
|
||||
address, false, true));
|
||||
}
|
||||
|
||||
void
|
||||
add_local_section(Sized_relobj<size, big_endian>* relobj,
|
||||
unsigned int input_shndx, unsigned int type,
|
||||
Output_data* od, unsigned int shndx, Address address)
|
||||
{
|
||||
this->add(od, Output_reloc_type(relobj, input_shndx, type, shndx,
|
||||
address, false, true));
|
||||
}
|
||||
|
||||
// A reloc against the STT_SECTION symbol of an output section.
|
||||
// OS is the Output_section that the relocation refers to; OD is
|
||||
@ -1101,7 +1169,7 @@ template<bool dynamic, int size, bool big_endian>
|
||||
class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
|
||||
: public Output_data_reloc_base<elfcpp::SHT_RELA, dynamic, size, big_endian>
|
||||
{
|
||||
private:
|
||||
private:
|
||||
typedef Output_data_reloc_base<elfcpp::SHT_RELA, dynamic, size,
|
||||
big_endian> Base;
|
||||
|
||||
@ -1154,7 +1222,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, false));
|
||||
addend, false, false));
|
||||
}
|
||||
|
||||
void
|
||||
@ -1164,7 +1232,7 @@ 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, false));
|
||||
address, addend, false, false));
|
||||
}
|
||||
|
||||
// Add a RELATIVE reloc against a local symbol.
|
||||
@ -1175,7 +1243,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, true));
|
||||
addend, true, false));
|
||||
}
|
||||
|
||||
void
|
||||
@ -1185,7 +1253,30 @@ 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, true));
|
||||
address, addend, true, false));
|
||||
}
|
||||
|
||||
// Add a reloc against a local section symbol. This will be
|
||||
// converted into a reloc against the STT_SECTION symbol of the
|
||||
// output section.
|
||||
|
||||
void
|
||||
add_local_section(Sized_relobj<size, big_endian>* relobj,
|
||||
unsigned int input_shndx, unsigned int type,
|
||||
Output_data* od, Address address, Addend addend)
|
||||
{
|
||||
this->add(od, Output_reloc_type(relobj, input_shndx, type, od, address,
|
||||
addend, false, true));
|
||||
}
|
||||
|
||||
void
|
||||
add_local_section(Sized_relobj<size, big_endian>* relobj,
|
||||
unsigned int input_shndx, unsigned int type,
|
||||
Output_data* od, unsigned int shndx, Address address,
|
||||
Addend addend)
|
||||
{
|
||||
this->add(od, Output_reloc_type(relobj, input_shndx, type, shndx,
|
||||
address, addend, false, true));
|
||||
}
|
||||
|
||||
// A reloc against the STT_SECTION symbol of an output section.
|
||||
|
@ -828,10 +828,10 @@ Target_x86_64::Scan::local(const General_options&,
|
||||
|
||||
case elfcpp::R_X86_64_64:
|
||||
// If building a shared library (or a position-independent
|
||||
// executable), we need to create a dynamic relocation for
|
||||
// this location. The relocation applied at link time will
|
||||
// apply the link-time value, so we flag the location with
|
||||
// an R_386_RELATIVE relocation so the dynamic loader can
|
||||
// executable), we need to create a dynamic relocation for this
|
||||
// location. The relocation applied at link time will apply the
|
||||
// link-time value, so we flag the location with an
|
||||
// R_X86_64_RELATIVE relocation so the dynamic loader can
|
||||
// relocate it easily.
|
||||
if (parameters->output_is_position_independent())
|
||||
{
|
||||
@ -850,18 +850,27 @@ Target_x86_64::Scan::local(const General_options&,
|
||||
case elfcpp::R_X86_64_16:
|
||||
case elfcpp::R_X86_64_8:
|
||||
// If building a shared library (or a position-independent
|
||||
// executable), we need to create a dynamic relocation for
|
||||
// this location. The relocation applied at link time will
|
||||
// apply the link-time value, so we flag the location with
|
||||
// an R_386_RELATIVE relocation so the dynamic loader can
|
||||
// relocate it easily.
|
||||
// executable), we need to create a dynamic relocation for this
|
||||
// location. We can't use an R_X86_64_RELATIVE relocation
|
||||
// because that is always a 64-bit relocation.
|
||||
if (parameters->output_is_position_independent())
|
||||
{
|
||||
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
|
||||
unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
|
||||
rela_dyn->add_local(object, r_sym, r_type, output_section,
|
||||
data_shndx, reloc.get_r_offset(),
|
||||
reloc.get_r_addend());
|
||||
if (lsym.get_st_type() != elfcpp::STT_SECTION)
|
||||
{
|
||||
unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
|
||||
rela_dyn->add_local(object, r_sym, r_type, output_section,
|
||||
data_shndx, reloc.get_r_offset(),
|
||||
reloc.get_r_addend());
|
||||
}
|
||||
else
|
||||
{
|
||||
gold_assert(lsym.get_st_value() == 0);
|
||||
rela_dyn->add_local_section(object, lsym.get_st_shndx(),
|
||||
r_type, output_section,
|
||||
data_shndx, reloc.get_r_offset(),
|
||||
reloc.get_r_addend());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -909,8 +918,12 @@ Target_x86_64::Scan::local(const General_options&,
|
||||
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);
|
||||
{
|
||||
gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
|
||||
rela_dyn->add_local(object, r_sym, r_type,
|
||||
got, object->local_got_offset(r_sym),
|
||||
0);
|
||||
}
|
||||
}
|
||||
}
|
||||
// For GOTPLT64, we'd normally want a PLT section, but since
|
||||
|
Loading…
Reference in New Issue
Block a user