aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2007-12-07 19:32:59 +0000
committerIan Lance Taylor <iant@google.com>2007-12-07 19:32:59 +0000
commite8c846c359fda086b5e550fc795cc1c05b6ee003 (patch)
treea7efff24a88e4874d11de980263ed408bd5d7a97
parentc68cf8ad105b1605718ea48e5f0f118b35be5654 (diff)
downloadgdb-e8c846c359fda086b5e550fc795cc1c05b6ee003.zip
gdb-e8c846c359fda086b5e550fc795cc1c05b6ee003.tar.gz
gdb-e8c846c359fda086b5e550fc795cc1c05b6ee003.tar.bz2
From Cary Coutant: Fix handling of RELATIVE RELA relocs.
-rw-r--r--gold/i386.cc43
-rw-r--r--gold/output.cc85
-rw-r--r--gold/output.h135
-rw-r--r--gold/symtab.cc1
-rw-r--r--gold/symtab.h16
-rw-r--r--gold/x86_64.cc31
6 files changed, 200 insertions, 111 deletions
diff --git a/gold/i386.cc b/gold/i386.cc
index 071940b..a03893c 100644
--- a/gold/i386.cc
+++ b/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,9 +960,12 @@ 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,
- 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());
}
// Create a GOT entry for the tp-relative offset.
Output_data_got<32, false>* got
@@ -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,
- got, gsym->got_offset());
- // Make sure we write the link-time value to the GOT.
- gsym->set_needs_value_in_got();
- }
+ rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE,
+ got, gsym->got_offset());
}
}
}
@@ -1264,9 +1268,10 @@ 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,
- reloc.get_r_offset());
+ 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.
Output_data_got<32, false>* got
diff --git a/gold/output.cc b/gold/output.cc
index 7fd901c..922a9e5 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -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,24 +800,16 @@ 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
- // as small as possible.
- sgsym = static_cast<Sized_symbol<size>*>(gsym);
- val = sgsym->value();
- }
+ 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;
diff --git a/gold/output.h b/gold/output.h
index 6c80d0a..172be49 100644
--- a/gold/output.h
+++ b/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.
diff --git a/gold/symtab.cc b/gold/symtab.cc
index a18d3ae..9187f32 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -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
diff --git a/gold/symtab.h b/gold/symtab.h
index 6d2577b..a4f1106 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -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
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index cb68730..bdc28d4 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -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,
- output_section, data_shndx,
- reloc.get_r_offset(), 0);
+ rela_dyn->add_local_relative(object, r_sym,
+ elfcpp::R_X86_64_RELATIVE,
+ output_section, data_shndx,
+ 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,
- got, gsym->got_offset(), 0);
- // Make sure we write the link-time value to the GOT.
- gsym->set_needs_value_in_got();
- }
+ rela_dyn->add_global_relative(gsym,
+ elfcpp::R_X86_64_RELATIVE,
+ got, gsym->got_offset(), 0);
}
}
// For GOTPLT64, we also need a PLT entry (but only if the