* object.h (Relobj::local_symbol_value): New function.

(Relobj::local_plt_offset): New function.
	(Relobj::local_has_got_offset): New function.
	(Relobj::local_got_offset): New function.
	(Relobj::set_local_got_offset): New function.
	(Relobj::do_local_symbol_value): New pure virtual function.
	(Relobj::do_local_plt_offset): Likewise.
	(Relobj::do_local_has_got_offset): Likewise.
	(Relobj::do_local_got_offset): Likewise.
	(Relobj::do_set_local_got_offset): Likewise.
	(Sized_relobj::do_local_has_got_offset): Rename from
	local_has_got_offset.
	(Sized_relobj::do_local_got_offset): Rename from local_got_offset.
	(Sized_relobj::do_set_local_got_offset): Rename from
	set_local_got_offset.
	(Sized_relobj_file::do_local_plt_offset): Rename from
	local_plt_offset.
	(Sized_relobj_file::do_local_symbol_value): New function.
	* object.cc (Sized_relobj_file::do_local_plt_offset): Rename from
	local_plt_offset.
	* output.cc (Output_data_got::Got_entry::write): Change object to
	Relobj.  Use local_symbol_value.
	(Output_data_got::add_global_with_rel): Change rel_dyn to
	Output_data_reloc_generic*.  Use add_global_generic.
	(Output_data_got::add_global_with_rela): Remove.  Change all
	callers to use add_global_with_rel.
	(Output_data_got::add_global_pair_with_rel): Change rel_dyn to
	Output_data_reloc_generic*.  Use add_global_generic.
	(Output_data_got::add_global_pair_with_rela): Remove.  Change all
	callers to use add_global_pair_with_rel.
	(Output_data_got::add_local): Change object to Relobj*.
	(Output_data_got::add_local_plt): Likewise.
	(Output_data_got::add_local_with_rel): Change object to Relobj*,
	change rel_dyn to Output_data_reloc_generic*.  Use
	add_local_generic.
	(Output_data_got::add_local_with_rela): Remove.  Change all
	callers to use all_local_with_rel.
	(Output_data_got::add_local_pair_with_rel): Change object to
	Relobj*, change rel_dyn to Output_data_reloc_generic*.  Use
	add_output_section_generic.
	(Output_data_got::add_local_pair_with_rela): Remove.  Change all
	callers to use add_local_pair_with_rel.
	(Output_data_got::reserve_local): Change object to Relobj*.
	* output.h: (class Output_data_reloc_generic): Add pure virtual
	declarations for add_global_generic, add_local_generic,
	add_output_section_generic.
	(class Output_data_reloc) [SHT_REL, SHT_RELA]: Implement new
	functions for Output_data_reloc_generic.  Update declarations for
	changes listed in output.cc.
	(class Output_data_got): Change template parameter to got_size.
	Don't define Rel_dyn or Rela_dyn.  Update declarations per above.
	* incremental.h (Sized_relobj_incr::do_local_symbol_value): New
	function.
	(Sized_relobj_incr::do_local_plt_offset): New function.
	* copy-relocs.cc (Copy_relocs::Copy_reloc_entry::emit): Call
	add_global_generic.
This commit is contained in:
Ian Lance Taylor 2011-12-19 21:07:16 +00:00
parent 984ac46443
commit 83896202bf
11 changed files with 475 additions and 264 deletions

View File

@ -1,3 +1,62 @@
2011-12-18 Ian Lance Taylor <iant@google.com>
* object.h (Relobj::local_symbol_value): New function.
(Relobj::local_plt_offset): New function.
(Relobj::local_has_got_offset): New function.
(Relobj::local_got_offset): New function.
(Relobj::set_local_got_offset): New function.
(Relobj::do_local_symbol_value): New pure virtual function.
(Relobj::do_local_plt_offset): Likewise.
(Relobj::do_local_has_got_offset): Likewise.
(Relobj::do_local_got_offset): Likewise.
(Relobj::do_set_local_got_offset): Likewise.
(Sized_relobj::do_local_has_got_offset): Rename from
local_has_got_offset.
(Sized_relobj::do_local_got_offset): Rename from local_got_offset.
(Sized_relobj::do_set_local_got_offset): Rename from
set_local_got_offset.
(Sized_relobj_file::do_local_plt_offset): Rename from
local_plt_offset.
(Sized_relobj_file::do_local_symbol_value): New function.
* object.cc (Sized_relobj_file::do_local_plt_offset): Rename from
local_plt_offset.
* output.cc (Output_data_got::Got_entry::write): Change object to
Relobj. Use local_symbol_value.
(Output_data_got::add_global_with_rel): Change rel_dyn to
Output_data_reloc_generic*. Use add_global_generic.
(Output_data_got::add_global_with_rela): Remove. Change all
callers to use add_global_with_rel.
(Output_data_got::add_global_pair_with_rel): Change rel_dyn to
Output_data_reloc_generic*. Use add_global_generic.
(Output_data_got::add_global_pair_with_rela): Remove. Change all
callers to use add_global_pair_with_rel.
(Output_data_got::add_local): Change object to Relobj*.
(Output_data_got::add_local_plt): Likewise.
(Output_data_got::add_local_with_rel): Change object to Relobj*,
change rel_dyn to Output_data_reloc_generic*. Use
add_local_generic.
(Output_data_got::add_local_with_rela): Remove. Change all
callers to use all_local_with_rel.
(Output_data_got::add_local_pair_with_rel): Change object to
Relobj*, change rel_dyn to Output_data_reloc_generic*. Use
add_output_section_generic.
(Output_data_got::add_local_pair_with_rela): Remove. Change all
callers to use add_local_pair_with_rel.
(Output_data_got::reserve_local): Change object to Relobj*.
* output.h: (class Output_data_reloc_generic): Add pure virtual
declarations for add_global_generic, add_local_generic,
add_output_section_generic.
(class Output_data_reloc) [SHT_REL, SHT_RELA]: Implement new
functions for Output_data_reloc_generic. Update declarations for
changes listed in output.cc.
(class Output_data_got): Change template parameter to got_size.
Don't define Rel_dyn or Rela_dyn. Update declarations per above.
* incremental.h (Sized_relobj_incr::do_local_symbol_value): New
function.
(Sized_relobj_incr::do_local_plt_offset): New function.
* copy-relocs.cc (Copy_relocs::Copy_reloc_entry::emit): Call
add_global_generic.
2011-12-17 Cary Coutant <ccoutant@google.com>
* dwarf_reader.cc (Sized_dwarf_line_info::read_lines): Add casts.

View File

@ -1,6 +1,6 @@
// copy-relocs.cc -- handle COPY relocations for gold.
// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@ -41,10 +41,10 @@ Copy_relocs<sh_type, size, big_endian>::Copy_reloc_entry::emit(
// emitted a COPY relocation, and we do not want to emit this
// dynamic relocation.
if (this->sym_->is_from_dynobj())
reloc_section->add_global(this->sym_, this->reloc_type_,
this->output_section_, this->relobj_,
this->shndx_, this->address_,
this->addend_);
reloc_section->add_global_generic(this->sym_, this->reloc_type_,
this->output_section_, this->relobj_,
this->shndx_, this->address_,
this->addend_);
}
// Copy_relocs methods.
@ -115,7 +115,8 @@ Copy_relocs<sh_type, size, big_endian>::emit_copy_reloc(
symtab->define_with_copy_reloc(sym, posd, offset);
// Add the COPY relocation to the dynamic reloc section.
reloc_section->add_global(sym, this->copy_reloc_type_, posd, offset, 0);
reloc_section->add_global_generic(sym, this->copy_reloc_type_, posd,
offset, 0);
}
// Make a COPY relocation for SYM and emit it.

View File

@ -1,6 +1,6 @@
// expression.cc -- expressions in linker scripts for gold
// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.

View File

@ -1,6 +1,6 @@
// inremental.h -- incremental linking support for gold -*- C++ -*-
// Copyright 2009, 2010 Free Software Foundation, Inc.
// Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
// Written by Mikolaj Zalewski <mikolajz@google.com>.
// This file is part of gold.
@ -1924,6 +1924,15 @@ class Sized_relobj_incr : public Sized_relobj<size, big_endian>
do_get_global_symbols() const
{ return &this->symbols_; }
// Return the value of a local symbol.
uint64_t
do_local_symbol_value(unsigned int, uint64_t) const
{ gold_unreachable(); }
unsigned int
do_local_plt_offset(unsigned int) const
{ gold_unreachable(); }
// Return the number of local symbols.
unsigned int
do_local_symbol_count() const

View File

@ -1819,7 +1819,8 @@ Sized_relobj_file<size, big_endian>::local_has_plt_offset(
template<int size, bool big_endian>
unsigned int
Sized_relobj_file<size, big_endian>::local_plt_offset(unsigned int symndx) const
Sized_relobj_file<size, big_endian>::do_local_plt_offset(
unsigned int symndx) const
{
typename Local_plt_offsets::const_iterator p =
this->local_plt_offsets_.find(symndx);

View File

@ -1009,6 +1009,39 @@ class Relobj : public Object
scan_relocs(Symbol_table* symtab, Layout* layout, Read_relocs_data* rd)
{ return this->do_scan_relocs(symtab, layout, rd); }
// Return the value of the local symbol whose index is SYMNDX, plus
// ADDEND. ADDEND is passed in so that we can correctly handle the
// section symbol for a merge section.
uint64_t
local_symbol_value(unsigned int symndx, uint64_t addend) const
{ return this->do_local_symbol_value(symndx, addend); }
// Return the PLT offset for a local symbol. It is an error to call
// this if it doesn't have one.
unsigned int
local_plt_offset(unsigned int symndx) const
{ return this->do_local_plt_offset(symndx); }
// Return whether the local symbol SYMNDX has a GOT offset of type
// GOT_TYPE.
bool
local_has_got_offset(unsigned int symndx, unsigned int got_type) const
{ return this->do_local_has_got_offset(symndx, got_type); }
// Return the GOT offset of type GOT_TYPE of the local symbol
// SYMNDX. It is an error to call this if the symbol does not have
// a GOT offset of the specified type.
unsigned int
local_got_offset(unsigned int symndx, unsigned int got_type) const
{ return this->do_local_got_offset(symndx, got_type); }
// Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
// to GOT_OFFSET.
void
set_local_got_offset(unsigned int symndx, unsigned int got_type,
unsigned int got_offset)
{ this->do_set_local_got_offset(symndx, got_type, got_offset); }
// The number of local symbols in the input symbol table.
virtual unsigned int
local_symbol_count() const
@ -1167,6 +1200,28 @@ class Relobj : public Object
virtual void
do_scan_relocs(Symbol_table*, Layout*, Read_relocs_data*) = 0;
// Return the value of a local symbol.
virtual uint64_t
do_local_symbol_value(unsigned int symndx, uint64_t addend) const = 0;
// Return the PLT offset of a local symbol.
virtual unsigned int
do_local_plt_offset(unsigned int symndx) const = 0;
// Return whether a local symbol has a GOT offset of a given type.
virtual bool
do_local_has_got_offset(unsigned int symndx,
unsigned int got_type) const = 0;
// Return the GOT offset of a given type of a local symbol.
virtual unsigned int
do_local_got_offset(unsigned int symndx, unsigned int got_type) const = 0;
// Set the GOT offset with a given type for a local symbol.
virtual void
do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
unsigned int got_offset) = 0;
// Return the number of local symbols--implemented by child class.
virtual unsigned int
do_local_symbol_count() const = 0;
@ -1775,47 +1830,6 @@ class Sized_relobj : public Relobj
return this->section_offsets_[shndx];
}
// Return whether the local symbol SYMNDX has a GOT offset.
// For TLS symbols, the GOT entry will hold its tp-relative offset.
bool
local_has_got_offset(unsigned int symndx, unsigned int got_type) const
{
Local_got_offsets::const_iterator p =
this->local_got_offsets_.find(symndx);
return (p != this->local_got_offsets_.end()
&& p->second->get_offset(got_type) != -1U);
}
// Return the GOT offset of the local symbol SYMNDX.
unsigned int
local_got_offset(unsigned int symndx, unsigned int got_type) const
{
Local_got_offsets::const_iterator p =
this->local_got_offsets_.find(symndx);
gold_assert(p != this->local_got_offsets_.end());
unsigned int off = p->second->get_offset(got_type);
gold_assert(off != -1U);
return off;
}
// Set the GOT offset of the local symbol SYMNDX to GOT_OFFSET.
void
set_local_got_offset(unsigned int symndx, unsigned int got_type,
unsigned int got_offset)
{
Local_got_offsets::const_iterator p =
this->local_got_offsets_.find(symndx);
if (p != this->local_got_offsets_.end())
p->second->set_offset(got_type, got_offset);
else
{
Got_offset_list* g = new Got_offset_list(got_type, got_offset);
std::pair<Local_got_offsets::iterator, bool> ins =
this->local_got_offsets_.insert(std::make_pair(symndx, g));
gold_assert(ins.second);
}
}
// Iterate over local symbols, calling a visitor class V for each GOT offset
// associated with a local symbol.
void
@ -1855,6 +1869,49 @@ class Sized_relobj : public Relobj
: convert_types<Address, uint64_t>(off));
}
// Return whether the local symbol SYMNDX has a GOT offset of type
// GOT_TYPE.
bool
do_local_has_got_offset(unsigned int symndx, unsigned int got_type) const
{
Local_got_offsets::const_iterator p =
this->local_got_offsets_.find(symndx);
return (p != this->local_got_offsets_.end()
&& p->second->get_offset(got_type) != -1U);
}
// Return the GOT offset of type GOT_TYPE of the local symbol
// SYMNDX.
unsigned int
do_local_got_offset(unsigned int symndx, unsigned int got_type) const
{
Local_got_offsets::const_iterator p =
this->local_got_offsets_.find(symndx);
gold_assert(p != this->local_got_offsets_.end());
unsigned int off = p->second->get_offset(got_type);
gold_assert(off != -1U);
return off;
}
// Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
// to GOT_OFFSET.
void
do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
unsigned int got_offset)
{
Local_got_offsets::const_iterator p =
this->local_got_offsets_.find(symndx);
if (p != this->local_got_offsets_.end())
p->second->set_offset(got_type, got_offset);
else
{
Got_offset_list* g = new Got_offset_list(got_type, got_offset);
std::pair<Local_got_offsets::iterator, bool> ins =
this->local_got_offsets_.insert(std::make_pair(symndx, g));
gold_assert(ins.second);
}
}
private:
// The GOT offsets of local symbols. This map also stores GOT offsets
// for tp-relative offsets for TLS symbols.
@ -2000,11 +2057,6 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
bool
local_has_plt_offset(unsigned int symndx) const;
// Return the PLT offset for a local symbol. It is an error to call
// this if it doesn't have one.
unsigned int
local_plt_offset(unsigned int symndx) const;
// Set the PLT offset of the local symbol SYMNDX.
void
set_local_plt_offset(unsigned int symndx, unsigned int plt_offset);
@ -2050,6 +2102,19 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
void
do_read_symbols(Read_symbols_data*);
// Return the value of a local symbol.
uint64_t
do_local_symbol_value(unsigned int symndx, uint64_t addend) const
{
const Symbol_value<size>* symval = this->local_symbol(symndx);
return symval->value(this, addend);
}
// Return the PLT offset for a local symbol. It is an error to call
// this if it doesn't have one.
unsigned int
do_local_plt_offset(unsigned int symndx) const;
// Return the number of local symbols.
unsigned int
do_local_symbol_count() const

View File

@ -1387,11 +1387,13 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
default:
{
const Sized_relobj_file<size, big_endian>* object = this->u_.object;
const Relobj* object = this->u_.object;
const unsigned int lsi = this->local_sym_index_;
const Symbol_value<size>* symval = object->local_symbol(lsi);
if (!this->use_plt_offset_)
val = symval->value(this->u_.object, 0);
{
uint64_t lval = object->local_symbol_value(lsi, 0);
val = convert_types<Valtype, uint64_t>(lval);
}
else
{
uint64_t plt_address =
@ -1448,7 +1450,7 @@ void
Output_data_got<size, big_endian>::add_global_with_rel(
Symbol* gsym,
unsigned int got_type,
Rel_dyn* rel_dyn,
Output_data_reloc_generic* rel_dyn,
unsigned int r_type)
{
if (gsym->has_got_offset(got_type))
@ -1456,23 +1458,7 @@ Output_data_got<size, big_endian>::add_global_with_rel(
unsigned int got_offset = this->add_got_entry(Got_entry());
gsym->set_got_offset(got_type, got_offset);
rel_dyn->add_global(gsym, r_type, this, got_offset);
}
template<int size, bool big_endian>
void
Output_data_got<size, big_endian>::add_global_with_rela(
Symbol* gsym,
unsigned int got_type,
Rela_dyn* rela_dyn,
unsigned int r_type)
{
if (gsym->has_got_offset(got_type))
return;
unsigned int got_offset = this->add_got_entry(Got_entry());
gsym->set_got_offset(got_type, got_offset);
rela_dyn->add_global(gsym, r_type, this, got_offset, 0);
rel_dyn->add_global_generic(gsym, r_type, this, got_offset, 0);
}
// Add a pair of entries for a global symbol to the GOT, and add
@ -1483,7 +1469,7 @@ void
Output_data_got<size, big_endian>::add_global_pair_with_rel(
Symbol* gsym,
unsigned int got_type,
Rel_dyn* rel_dyn,
Output_data_reloc_generic* rel_dyn,
unsigned int r_type_1,
unsigned int r_type_2)
{
@ -1492,30 +1478,11 @@ Output_data_got<size, big_endian>::add_global_pair_with_rel(
unsigned int got_offset = this->add_got_entry_pair(Got_entry(), Got_entry());
gsym->set_got_offset(got_type, got_offset);
rel_dyn->add_global(gsym, r_type_1, this, got_offset);
rel_dyn->add_global_generic(gsym, r_type_1, this, got_offset, 0);
if (r_type_2 != 0)
rel_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8);
}
template<int size, bool big_endian>
void
Output_data_got<size, big_endian>::add_global_pair_with_rela(
Symbol* gsym,
unsigned int got_type,
Rela_dyn* rela_dyn,
unsigned int r_type_1,
unsigned int r_type_2)
{
if (gsym->has_got_offset(got_type))
return;
unsigned int got_offset = this->add_got_entry_pair(Got_entry(), Got_entry());
gsym->set_got_offset(got_type, got_offset);
rela_dyn->add_global(gsym, r_type_1, this, got_offset, 0);
if (r_type_2 != 0)
rela_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8, 0);
rel_dyn->add_global_generic(gsym, r_type_2, this,
got_offset + size / 8, 0);
}
// Add an entry for a local symbol to the GOT. This returns true if
@ -1525,7 +1492,7 @@ Output_data_got<size, big_endian>::add_global_pair_with_rela(
template<int size, bool big_endian>
bool
Output_data_got<size, big_endian>::add_local(
Sized_relobj_file<size, big_endian>* object,
Relobj* object,
unsigned int symndx,
unsigned int got_type)
{
@ -1543,7 +1510,7 @@ Output_data_got<size, big_endian>::add_local(
template<int size, bool big_endian>
bool
Output_data_got<size, big_endian>::add_local_plt(
Sized_relobj_file<size, big_endian>* object,
Relobj* object,
unsigned int symndx,
unsigned int got_type)
{
@ -1562,10 +1529,10 @@ Output_data_got<size, big_endian>::add_local_plt(
template<int size, bool big_endian>
void
Output_data_got<size, big_endian>::add_local_with_rel(
Sized_relobj_file<size, big_endian>* object,
Relobj* object,
unsigned int symndx,
unsigned int got_type,
Rel_dyn* rel_dyn,
Output_data_reloc_generic* rel_dyn,
unsigned int r_type)
{
if (object->local_has_got_offset(symndx, got_type))
@ -1573,24 +1540,7 @@ Output_data_got<size, big_endian>::add_local_with_rel(
unsigned int got_offset = this->add_got_entry(Got_entry());
object->set_local_got_offset(symndx, got_type, got_offset);
rel_dyn->add_local(object, symndx, r_type, this, got_offset);
}
template<int size, bool big_endian>
void
Output_data_got<size, big_endian>::add_local_with_rela(
Sized_relobj_file<size, big_endian>* object,
unsigned int symndx,
unsigned int got_type,
Rela_dyn* rela_dyn,
unsigned int r_type)
{
if (object->local_has_got_offset(symndx, got_type))
return;
unsigned int got_offset = this->add_got_entry(Got_entry());
object->set_local_got_offset(symndx, got_type, got_offset);
rela_dyn->add_local(object, symndx, r_type, this, got_offset, 0);
rel_dyn->add_local_generic(object, symndx, r_type, this, got_offset, 0);
}
// Add a pair of entries for a local symbol to the GOT, and add
@ -1599,11 +1549,11 @@ Output_data_got<size, big_endian>::add_local_with_rela(
template<int size, bool big_endian>
void
Output_data_got<size, big_endian>::add_local_pair_with_rel(
Sized_relobj_file<size, big_endian>* object,
Relobj* object,
unsigned int symndx,
unsigned int shndx,
unsigned int got_type,
Rel_dyn* rel_dyn,
Output_data_reloc_generic* rel_dyn,
unsigned int r_type_1,
unsigned int r_type_2)
{
@ -1615,35 +1565,11 @@ Output_data_got<size, big_endian>::add_local_pair_with_rel(
Got_entry(object, symndx, false));
object->set_local_got_offset(symndx, got_type, got_offset);
Output_section* os = object->output_section(shndx);
rel_dyn->add_output_section(os, r_type_1, this, got_offset);
rel_dyn->add_output_section_generic(os, r_type_1, this, got_offset, 0);
if (r_type_2 != 0)
rel_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8);
}
template<int size, bool big_endian>
void
Output_data_got<size, big_endian>::add_local_pair_with_rela(
Sized_relobj_file<size, big_endian>* object,
unsigned int symndx,
unsigned int shndx,
unsigned int got_type,
Rela_dyn* rela_dyn,
unsigned int r_type_1,
unsigned int r_type_2)
{
if (object->local_has_got_offset(symndx, got_type))
return;
unsigned int got_offset =
this->add_got_entry_pair(Got_entry(),
Got_entry(object, symndx, false));
object->set_local_got_offset(symndx, got_type, got_offset);
Output_section* os = object->output_section(shndx);
rela_dyn->add_output_section(os, r_type_1, this, got_offset, 0);
if (r_type_2 != 0)
rela_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8, 0);
rel_dyn->add_output_section_generic(os, r_type_2, this,
got_offset + size / 8, 0);
}
// Reserve a slot in the GOT for a local symbol or the second slot of a pair.
@ -1652,7 +1578,7 @@ template<int size, bool big_endian>
void
Output_data_got<size, big_endian>::reserve_local(
unsigned int i,
Sized_relobj<size, big_endian>* object,
Relobj* object,
unsigned int sym_index,
unsigned int got_type)
{

View File

@ -1397,6 +1397,55 @@ class Output_data_reloc_generic : public Output_section_data_build
sort_relocs() const
{ return this->sort_relocs_; }
// Add a reloc of type TYPE against the global symbol GSYM. The
// relocation applies to the data at offset ADDRESS within OD.
virtual void
add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
uint64_t address, uint64_t addend) = 0;
// Add a reloc of type TYPE against the global symbol GSYM. The
// relocation applies to data at offset ADDRESS within section SHNDX
// of object file RELOBJ. OD is the associated output section.
virtual void
add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
Relobj* relobj, unsigned int shndx, uint64_t address,
uint64_t addend) = 0;
// Add a reloc of type TYPE against the local symbol LOCAL_SYM_INDEX
// in RELOBJ. The relocation applies to the data at offset ADDRESS
// within OD.
virtual void
add_local_generic(Relobj* relobj, unsigned int local_sym_index,
unsigned int type, Output_data* od, uint64_t address,
uint64_t addend) = 0;
// Add a reloc of type TYPE against the local symbol LOCAL_SYM_INDEX
// in RELOBJ. The relocation applies to the data at offset ADDRESS
// within section SHNDX of RELOBJ. OD is the associated output
// section.
virtual void
add_local_generic(Relobj* relobj, unsigned int local_sym_index,
unsigned int type, Output_data* od, unsigned int shndx,
uint64_t address, uint64_t addend) = 0;
// Add a reloc of type TYPE against the STT_SECTION symbol of the
// output section OS. The relocation applies to the data at offset
// ADDRESS within OD.
virtual void
add_output_section_generic(Output_section *os, unsigned int type,
Output_data* od, uint64_t address,
uint64_t addend) = 0;
// Add a reloc of type TYPE against the STT_SECTION symbol of the
// output section OS. The relocation applies to the data at offset
// ADDRESS within section SHNDX of RELOBJ. OD is the associated
// output section.
virtual void
add_output_section_generic(Output_section* os, unsigned int type,
Output_data* od, Relobj* relobj,
unsigned int shndx, uint64_t address,
uint64_t addend) = 0;
protected:
// Note that we've added another relative reloc.
void
@ -1518,23 +1567,27 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
{ this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
false, false)); }
// These are to simplify the Copy_relocs class.
void
add_global(Symbol* gsym, unsigned int type, Output_data* od, Address address,
Address addend)
add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
uint64_t address, uint64_t addend)
{
gold_assert(addend == 0);
this->add_global(gsym, type, od, address);
this->add(od, Output_reloc_type(gsym, type, od,
convert_types<Address, uint64_t>(address),
false, false));
}
void
add_global(Symbol* gsym, unsigned int type, Output_data* od,
Sized_relobj<size, big_endian>* relobj,
unsigned int shndx, Address address, Address addend)
add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
Relobj* relobj, unsigned int shndx, uint64_t address,
uint64_t addend)
{
gold_assert(addend == 0);
this->add_global(gsym, type, od, relobj, shndx, address);
Sized_relobj<size, big_endian>* sized_relobj =
static_cast<Sized_relobj<size, big_endian>*>(relobj);
this->add(od, Output_reloc_type(gsym, type, sized_relobj, shndx,
convert_types<Address, uint64_t>(address),
false, false));
}
// Add a RELATIVE reloc against a global symbol. The final relocation
@ -1592,6 +1645,32 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
address, false, false, false, false));
}
void
add_local_generic(Relobj* relobj, unsigned int local_sym_index,
unsigned int type, Output_data* od, uint64_t address,
uint64_t addend)
{
gold_assert(addend == 0);
Sized_relobj<size, big_endian>* sized_relobj =
static_cast<Sized_relobj<size, big_endian> *>(relobj);
this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, od,
convert_types<Address, uint64_t>(address),
false, false, false, false));
}
void
add_local_generic(Relobj* relobj, unsigned int local_sym_index,
unsigned int type, Output_data* od, unsigned int shndx,
uint64_t address, uint64_t addend)
{
gold_assert(addend == 0);
Sized_relobj<size, big_endian>* sized_relobj =
static_cast<Sized_relobj<size, big_endian>*>(relobj);
this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, shndx,
convert_types<Address, uint64_t>(address),
false, false, false, false));
}
// Add a RELATIVE reloc against a local symbol.
void
@ -1671,6 +1750,29 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
unsigned int shndx, Address address)
{ this->add(od, Output_reloc_type(os, type, relobj, shndx, address)); }
void
add_output_section_generic(Output_section* os, unsigned int type,
Output_data* od, uint64_t address,
uint64_t addend)
{
gold_assert(addend == 0);
this->add(od, Output_reloc_type(os, type, od,
convert_types<Address, uint64_t>(address)));
}
void
add_output_section_generic(Output_section* os, unsigned int type,
Output_data* od, Relobj* relobj,
unsigned int shndx, uint64_t address,
uint64_t addend)
{
gold_assert(addend == 0);
Sized_relobj<size, big_endian>* sized_relobj =
static_cast<Sized_relobj<size, big_endian>*>(relobj);
this->add(od, Output_reloc_type(os, type, sized_relobj, shndx,
convert_types<Address, uint64_t>(address)));
}
// Add an absolute relocation.
void
@ -1733,6 +1835,29 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
{ this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
addend, false, false)); }
void
add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
uint64_t address, uint64_t addend)
{
this->add(od, Output_reloc_type(gsym, type, od,
convert_types<Address, uint64_t>(address),
convert_types<Addend, uint64_t>(addend),
false, false));
}
void
add_global_generic(Symbol* gsym, unsigned int type, Output_data* od,
Relobj* relobj, unsigned int shndx, uint64_t address,
uint64_t addend)
{
Sized_relobj<size, big_endian>* sized_relobj =
static_cast<Sized_relobj<size, big_endian>*>(relobj);
this->add(od, Output_reloc_type(gsym, type, sized_relobj, shndx,
convert_types<Address, uint64_t>(address),
convert_types<Addend, uint64_t>(addend),
false, 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
@ -1790,6 +1915,32 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
false));
}
void
add_local_generic(Relobj* relobj, unsigned int local_sym_index,
unsigned int type, Output_data* od, uint64_t address,
uint64_t addend)
{
Sized_relobj<size, big_endian>* sized_relobj =
static_cast<Sized_relobj<size, big_endian> *>(relobj);
this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, od,
convert_types<Address, uint64_t>(address),
convert_types<Addend, uint64_t>(addend),
false, false, false, false));
}
void
add_local_generic(Relobj* relobj, unsigned int local_sym_index,
unsigned int type, Output_data* od, unsigned int shndx,
uint64_t address, uint64_t addend)
{
Sized_relobj<size, big_endian>* sized_relobj =
static_cast<Sized_relobj<size, big_endian>*>(relobj);
this->add(od, Output_reloc_type(sized_relobj, local_sym_index, type, shndx,
convert_types<Address, uint64_t>(address),
convert_types<Addend, uint64_t>(addend),
false, false, false, false));
}
// Add a RELATIVE reloc against a local symbol.
void
@ -1875,6 +2026,29 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
{ this->add(od, Output_reloc_type(os, type, relobj, shndx, address,
addend)); }
void
add_output_section_generic(Output_section* os, unsigned int type,
Output_data* od, uint64_t address,
uint64_t addend)
{
this->add(od, Output_reloc_type(os, type, od,
convert_types<Address, uint64_t>(address),
convert_types<Addend, uint64_t>(addend)));
}
void
add_output_section_generic(Output_section* os, unsigned int type,
Output_data* od, Relobj* relobj,
unsigned int shndx, uint64_t address,
uint64_t addend)
{
Sized_relobj<size, big_endian>* sized_relobj =
static_cast<Sized_relobj<size, big_endian>*>(relobj);
this->add(od, Output_reloc_type(os, type, sized_relobj, shndx,
convert_types<Address, uint64_t>(address),
convert_types<Addend, uint64_t>(addend)));
}
// Add an absolute relocation.
void
@ -1974,29 +2148,28 @@ class Output_data_group : public Output_section_data
// Output_data_got is used to manage a GOT. Each entry in the GOT is
// for one symbol--either a global symbol or a local symbol in an
// object. The target specific code adds entries to the GOT as
// needed.
// needed. The GOT_SIZE template parameter is the size in bits of a
// GOT entry, typically 32 or 64.
template<int size, bool big_endian>
template<int got_size, bool big_endian>
class Output_data_got : public Output_section_data_build
{
public:
typedef typename elfcpp::Elf_types<size>::Elf_Addr Valtype;
typedef Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian> Rel_dyn;
typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian> Rela_dyn;
typedef typename elfcpp::Elf_types<got_size>::Elf_Addr Valtype;
Output_data_got()
: Output_section_data_build(Output_data::default_alignment_for_size(size)),
: Output_section_data_build(Output_data::default_alignment_for_size(got_size)),
entries_(), free_list_()
{ }
Output_data_got(off_t data_size)
: Output_section_data_build(data_size,
Output_data::default_alignment_for_size(size)),
Output_data::default_alignment_for_size(got_size)),
entries_(), free_list_()
{
// For an incremental update, we have an existing GOT section.
// Initialize the list of entries and the free list.
this->entries_.resize(data_size / (size / 8));
this->entries_.resize(data_size / (got_size / 8));
this->free_list_.init(data_size, false);
}
@ -2014,62 +2187,39 @@ class Output_data_got : public Output_section_data_build
// relocation of type R_TYPE for the GOT entry.
void
add_global_with_rel(Symbol* gsym, unsigned int got_type,
Rel_dyn* rel_dyn, unsigned int r_type);
void
add_global_with_rela(Symbol* gsym, unsigned int got_type,
Rela_dyn* rela_dyn, unsigned int r_type);
Output_data_reloc_generic* rel_dyn, unsigned int r_type);
// Add a pair of entries for a global symbol to the GOT, and add
// dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively.
void
add_global_pair_with_rel(Symbol* gsym, unsigned int got_type,
Rel_dyn* rel_dyn, unsigned int r_type_1,
unsigned int r_type_2);
void
add_global_pair_with_rela(Symbol* gsym, unsigned int got_type,
Rela_dyn* rela_dyn, unsigned int r_type_1,
unsigned int r_type_2);
Output_data_reloc_generic* rel_dyn,
unsigned int r_type_1, unsigned int r_type_2);
// Add an entry for a local symbol to the GOT. This returns true if
// this is a new GOT entry, false if the symbol already has a GOT
// entry.
bool
add_local(Sized_relobj_file<size, big_endian>* object, unsigned int sym_index,
unsigned int got_type);
add_local(Relobj* object, unsigned int sym_index, unsigned int got_type);
// Like add_local, but use the PLT offset of the local symbol if it
// has one.
bool
add_local_plt(Sized_relobj_file<size, big_endian>* object,
unsigned int sym_index,
unsigned int got_type);
add_local_plt(Relobj* object, unsigned int sym_index, unsigned int got_type);
// Add an entry for a local symbol to the GOT, and add a dynamic
// relocation of type R_TYPE for the GOT entry.
void
add_local_with_rel(Sized_relobj_file<size, big_endian>* object,
unsigned int sym_index, unsigned int got_type,
Rel_dyn* rel_dyn, unsigned int r_type);
void
add_local_with_rela(Sized_relobj_file<size, big_endian>* object,
unsigned int sym_index, unsigned int got_type,
Rela_dyn* rela_dyn, unsigned int r_type);
add_local_with_rel(Relobj* object, unsigned int sym_index,
unsigned int got_type, Output_data_reloc_generic* rel_dyn,
unsigned int r_type);
// Add a pair of entries for a local symbol to the GOT, and add
// dynamic relocations of type R_TYPE_1 and R_TYPE_2, respectively.
void
add_local_pair_with_rel(Sized_relobj_file<size, big_endian>* object,
unsigned int sym_index, unsigned int shndx,
unsigned int got_type, Rel_dyn* rel_dyn,
unsigned int r_type_1, unsigned int r_type_2);
void
add_local_pair_with_rela(Sized_relobj_file<size, big_endian>* object,
unsigned int sym_index, unsigned int shndx,
unsigned int got_type, Rela_dyn* rela_dyn,
add_local_pair_with_rel(Relobj* object, unsigned int sym_index,
unsigned int shndx, unsigned int got_type,
Output_data_reloc_generic* rel_dyn,
unsigned int r_type_1, unsigned int r_type_2);
// Add a constant to the GOT. This returns the offset of the new
@ -2084,12 +2234,12 @@ class Output_data_got : public Output_section_data_build
// Reserve a slot in the GOT.
void
reserve_slot(unsigned int i)
{ this->free_list_.remove(i * size / 8, (i + 1) * size / 8); }
{ this->free_list_.remove(i * got_size / 8, (i + 1) * got_size / 8); }
// Reserve a slot in the GOT for a local symbol.
void
reserve_local(unsigned int i, Sized_relobj<size, big_endian>* object,
unsigned int sym_index, unsigned int got_type);
reserve_local(unsigned int i, Relobj* object, unsigned int sym_index,
unsigned int got_type);
// Reserve a slot in the GOT for a global symbol.
void
@ -2121,8 +2271,8 @@ class Output_data_got : public Output_section_data_build
{ this->u_.gsym = gsym; }
// Create a local symbol entry.
Got_entry(Sized_relobj_file<size, big_endian>* object,
unsigned int local_sym_index, bool use_plt_offset)
Got_entry(Relobj* object, unsigned int local_sym_index,
bool use_plt_offset)
: local_sym_index_(local_sym_index), use_plt_offset_(use_plt_offset)
{
gold_assert(local_sym_index != GSYM_CODE
@ -2153,7 +2303,7 @@ class Output_data_got : public Output_section_data_build
union
{
// For a local symbol, the object.
Sized_relobj_file<size, big_endian>* object;
Relobj* object;
// For a global symbol, the symbol.
Symbol* gsym;
// For a constant, the constant.
@ -2179,7 +2329,7 @@ class Output_data_got : public Output_section_data_build
// Return the offset into the GOT of GOT entry I.
unsigned int
got_offset(unsigned int i) const
{ return i * (size / 8); }
{ return i * (got_size / 8); }
// Return the offset into the GOT of the last entry added.
unsigned int

View File

@ -1566,8 +1566,8 @@ Target_powerpc<size, big_endian>::Scan::global(
if (gsym->is_from_dynobj()
|| gsym->is_undefined()
|| gsym->is_preemptible())
got->add_global_with_rela(gsym, GOT_TYPE_STANDARD, rela_dyn,
elfcpp::R_POWERPC_GLOB_DAT);
got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, rela_dyn,
elfcpp::R_POWERPC_GLOB_DAT);
else if (!gsym->has_got_offset(GOT_TYPE_STANDARD))
{
unsigned int off = got->add_constant(0);

View File

@ -1998,14 +1998,14 @@ Target_sparc<size, big_endian>::Scan::local(
object->error(_("local symbol %u has bad shndx %u"),
r_sym, shndx);
else
got->add_local_pair_with_rela(object, r_sym,
lsym.get_st_shndx(),
GOT_TYPE_TLS_PAIR,
target->rela_dyn_section(layout),
(size == 64
? elfcpp::R_SPARC_TLS_DTPMOD64
: elfcpp::R_SPARC_TLS_DTPMOD32),
0);
got->add_local_pair_with_rel(object, r_sym,
lsym.get_st_shndx(),
GOT_TYPE_TLS_PAIR,
target->rela_dyn_section(layout),
(size == 64
? elfcpp::R_SPARC_TLS_DTPMOD64
: elfcpp::R_SPARC_TLS_DTPMOD32),
0);
if (r_type == elfcpp::R_SPARC_TLS_GD_CALL)
generate_tls_call(symtab, layout, target);
}
@ -2339,8 +2339,8 @@ Target_sparc<size, big_endian>::Scan::global(
if (gsym->is_from_dynobj()
|| gsym->is_undefined()
|| gsym->is_preemptible())
got->add_global_with_rela(gsym, GOT_TYPE_STANDARD, rela_dyn,
elfcpp::R_SPARC_GLOB_DAT);
got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, rela_dyn,
elfcpp::R_SPARC_GLOB_DAT);
else if (!gsym->has_got_offset(GOT_TYPE_STANDARD))
{
unsigned int off = got->add_constant(0);
@ -2389,14 +2389,14 @@ Target_sparc<size, big_endian>::Scan::global(
// dtv-relative offset.
Output_data_got<size, big_endian>* got
= target->got_section(symtab, layout);
got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_PAIR,
target->rela_dyn_section(layout),
(size == 64 ?
elfcpp::R_SPARC_TLS_DTPMOD64 :
elfcpp::R_SPARC_TLS_DTPMOD32),
(size == 64 ?
elfcpp::R_SPARC_TLS_DTPOFF64 :
elfcpp::R_SPARC_TLS_DTPOFF32));
got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
target->rela_dyn_section(layout),
(size == 64
? elfcpp::R_SPARC_TLS_DTPMOD64
: elfcpp::R_SPARC_TLS_DTPMOD32),
(size == 64
? elfcpp::R_SPARC_TLS_DTPOFF64
: elfcpp::R_SPARC_TLS_DTPOFF32));
// Emit R_SPARC_WPLT30 against "__tls_get_addr"
if (r_type == elfcpp::R_SPARC_TLS_GD_CALL)
@ -2407,11 +2407,11 @@ Target_sparc<size, big_endian>::Scan::global(
// Create a GOT entry for the tp-relative offset.
Output_data_got<size, big_endian>* got
= target->got_section(symtab, layout);
got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET,
target->rela_dyn_section(layout),
(size == 64 ?
elfcpp::R_SPARC_TLS_TPOFF64 :
elfcpp::R_SPARC_TLS_TPOFF32));
got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
target->rela_dyn_section(layout),
(size == 64 ?
elfcpp::R_SPARC_TLS_TPOFF64 :
elfcpp::R_SPARC_TLS_TPOFF32));
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_global(object, r_type, gsym);
@ -2462,11 +2462,11 @@ Target_sparc<size, big_endian>::Scan::global(
// Create a GOT entry for the tp-relative offset.
Output_data_got<size, big_endian>* got
= target->got_section(symtab, layout);
got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET,
target->rela_dyn_section(layout),
(size == 64 ?
elfcpp::R_SPARC_TLS_TPOFF64 :
elfcpp::R_SPARC_TLS_TPOFF32));
got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
target->rela_dyn_section(layout),
(size == 64
? elfcpp::R_SPARC_TLS_TPOFF64
: elfcpp::R_SPARC_TLS_TPOFF32));
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_global(object, r_type, gsym);

View File

@ -2137,11 +2137,11 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
object->error(_("local symbol %u has bad shndx %u"),
r_sym, shndx);
else
got->add_local_pair_with_rela(object, r_sym,
shndx,
GOT_TYPE_TLS_PAIR,
target->rela_dyn_section(layout),
elfcpp::R_X86_64_DTPMOD64, 0);
got->add_local_pair_with_rel(object, r_sym,
shndx,
GOT_TYPE_TLS_PAIR,
target->rela_dyn_section(layout),
elfcpp::R_X86_64_DTPMOD64, 0);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_local(object, r_type);
@ -2207,9 +2207,9 @@ Target_x86_64::Scan::local(Symbol_table* symtab,
Output_data_got<64, false>* got
= target->got_section(symtab, layout);
unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
got->add_local_with_rela(object, r_sym, GOT_TYPE_TLS_OFFSET,
target->rela_dyn_section(layout),
elfcpp::R_X86_64_TPOFF64);
got->add_local_with_rel(object, r_sym, GOT_TYPE_TLS_OFFSET,
target->rela_dyn_section(layout),
elfcpp::R_X86_64_TPOFF64);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_local(object, r_type);
@ -2481,8 +2481,8 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
&& parameters->options().shared())
|| (gsym->type() == elfcpp::STT_GNU_IFUNC
&& parameters->options().output_is_position_independent()))
got->add_global_with_rela(gsym, GOT_TYPE_STANDARD, rela_dyn,
elfcpp::R_X86_64_GLOB_DAT);
got->add_global_with_rel(gsym, GOT_TYPE_STANDARD, rela_dyn,
elfcpp::R_X86_64_GLOB_DAT);
else
{
// For a STT_GNU_IFUNC symbol we want to write the PLT
@ -2580,19 +2580,19 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
// dtv-relative offset.
Output_data_got<64, false>* got
= target->got_section(symtab, layout);
got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_PAIR,
target->rela_dyn_section(layout),
elfcpp::R_X86_64_DTPMOD64,
elfcpp::R_X86_64_DTPOFF64);
got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
target->rela_dyn_section(layout),
elfcpp::R_X86_64_DTPMOD64,
elfcpp::R_X86_64_DTPOFF64);
}
else if (optimized_type == tls::TLSOPT_TO_IE)
{
// Create a GOT entry for the tp-relative offset.
Output_data_got<64, false>* got
= target->got_section(symtab, layout);
got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET,
target->rela_dyn_section(layout),
elfcpp::R_X86_64_TPOFF64);
got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
target->rela_dyn_section(layout),
elfcpp::R_X86_64_TPOFF64);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_global(object, r_type, gsym);
@ -2613,17 +2613,17 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
target->got_section(symtab, layout);
Output_data_got<64, false>* got = target->got_tlsdesc_section();
Reloc_section* rt = target->rela_tlsdesc_section(layout);
got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_DESC, rt,
elfcpp::R_X86_64_TLSDESC, 0);
got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC, rt,
elfcpp::R_X86_64_TLSDESC, 0);
}
else if (optimized_type == tls::TLSOPT_TO_IE)
{
// Create a GOT entry for the tp-relative offset.
Output_data_got<64, false>* got
= target->got_section(symtab, layout);
got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET,
target->rela_dyn_section(layout),
elfcpp::R_X86_64_TPOFF64);
got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
target->rela_dyn_section(layout),
elfcpp::R_X86_64_TPOFF64);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_global(object, r_type, gsym);
@ -2653,9 +2653,9 @@ Target_x86_64::Scan::global(Symbol_table* symtab,
// Create a GOT entry for the tp-relative offset.
Output_data_got<64, false>* got
= target->got_section(symtab, layout);
got->add_global_with_rela(gsym, GOT_TYPE_TLS_OFFSET,
target->rela_dyn_section(layout),
elfcpp::R_X86_64_TPOFF64);
got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
target->rela_dyn_section(layout),
elfcpp::R_X86_64_TPOFF64);
}
else if (optimized_type != tls::TLSOPT_TO_LE)
unsupported_reloc_global(object, r_type, gsym);