2010-02-24 Doug Kwan <dougkwan@google.com>

* arm.cc (Arm_output_data_got): New class.
	(ARM_TCB_SIZE): New constant
	(Target_arm): Use Arm_output_data_got instead of Output_data_got.
	(Arm_output_section::fix_exidx_coverage): Add a parameter for layout.
	If user uses a script with a SECTIONS clause, issue only a warning
	for a misplaced EXIDX input section.  Otherwise, issue an error.
 	(Arm_relobj::do_gc_process_relocs): Exit early if we are not doing
	garbage collection.
	(Target_arm::got_mode_index_entry): Handle static linking.
	(Target_arm::Scan::local): Ditto.
	(Target_arm::Scan::global): Ditto.
	(Target_arm::Relocate::relocate_tls): Handle static linking.  Fix
	all incorrectly implemented relocations.
	(Target_arm::fix_exidx_coverage): Pass layout to
	Arm_output_section::fix_exidx_coverage.
	* layout.cc (Layout::section_name_mapping): Remove trailing dots
	from ".ARM.exidx." and ".ARM.extab.".
This commit is contained in:
Doug Kwan 2010-02-24 20:45:12 +00:00
parent 0723dbf578
commit 4a54abbbe9
3 changed files with 447 additions and 49 deletions

View file

@ -1,3 +1,23 @@
2010-02-24 Doug Kwan <dougkwan@google.com>
* arm.cc (Arm_output_data_got): New class.
(ARM_TCB_SIZE): New constant
(Target_arm): Use Arm_output_data_got instead of Output_data_got.
(Arm_output_section::fix_exidx_coverage): Add a parameter for layout.
If user uses a script with a SECTIONS clause, issue only a warning
for a misplaced EXIDX input section. Otherwise, issue an error.
(Arm_relobj::do_gc_process_relocs): Exit early if we are not doing
garbage collection.
(Target_arm::got_mode_index_entry): Handle static linking.
(Target_arm::Scan::local): Ditto.
(Target_arm::Scan::global): Ditto.
(Target_arm::Relocate::relocate_tls): Handle static linking. Fix
all incorrectly implemented relocations.
(Target_arm::fix_exidx_coverage): Pass layout to
Arm_output_section::fix_exidx_coverage.
* layout.cc (Layout::section_name_mapping): Remove trailing dots
from ".ARM.exidx." and ".ARM.extab.".
2010-02-23 Viktor Kutuzov <vkutuzov@accesssoftek.com>
* arm.cc (Target_arm::do_finalize_sections): Create attribute

View file

@ -83,6 +83,9 @@ class Arm_relobj;
template<bool big_endian>
class Arm_relocate_functions;
template<bool big_endian>
class Arm_output_data_got;
template<bool big_endian>
class Target_arm;
@ -97,6 +100,9 @@ const int32_t THM_MAX_BWD_BRANCH_OFFSET = (-(1 << 22) + 4);
const int32_t THM2_MAX_FWD_BRANCH_OFFSET = (((1 << 24) - 2) + 4);
const int32_t THM2_MAX_BWD_BRANCH_OFFSET = (-(1 << 24) + 4);
// Thread Control Block size.
const size_t ARM_TCB_SIZE = 8;
// The arm target class.
//
// This is a very simple port of gold for ARM-EABI. It is intended for
@ -1318,7 +1324,8 @@ class Arm_output_section : public Output_section
// is a list of text input sections sorted in ascending order of their
// output addresses.
void
fix_exidx_coverage(const Text_section_list& sorted_text_section,
fix_exidx_coverage(Layout* layout,
const Text_section_list& sorted_text_section,
Symbol_table* symtab);
private:
@ -1778,6 +1785,144 @@ class Cortex_a8_reloc
Arm_address destination_;
};
// Arm_output_data_got class. We derive this from Output_data_got to add
// extra methods to handle TLS relocations in a static link.
template<bool big_endian>
class Arm_output_data_got : public Output_data_got<32, big_endian>
{
public:
Arm_output_data_got(Symbol_table* symtab, Layout* layout)
: Output_data_got<32, big_endian>(), symbol_table_(symtab), layout_(layout)
{ }
// Add a static entry for the GOT entry at OFFSET. GSYM is a global
// symbol and R_TYPE is the code of a dynamic relocation that needs to be
// applied in a static link.
void
add_static_reloc(unsigned int got_offset, unsigned int r_type, Symbol* gsym)
{ this->static_relocs_.push_back(Static_reloc(got_offset, r_type, gsym)); }
// Add a static reloc for the GOT entry at OFFSET. RELOBJ is an object
// defining a local symbol with INDEX. R_TYPE is the code of a dynamic
// relocation that needs to be applied in a static link.
void
add_static_reloc(unsigned int got_offset, unsigned int r_type,
Sized_relobj<32, big_endian>* relobj, unsigned int index)
{
this->static_relocs_.push_back(Static_reloc(got_offset, r_type, relobj,
index));
}
// Add a GOT pair for R_ARM_TLS_GD32. The creates a pair of GOT entries.
// The first one is initialized to be 1, which is the module index for
// the main executable and the second one 0. A reloc of the type
// R_ARM_TLS_DTPOFF32 will be created for the second GOT entry and will
// be applied by gold. GSYM is a global symbol.
void
add_tls_gd32_with_static_reloc(unsigned int got_type, Symbol* gsym);
// Same as the above but for a local symbol in OBJECT with INDEX.
void
add_tls_gd32_with_static_reloc(unsigned int got_type,
Sized_relobj<32, big_endian>* object,
unsigned int index);
protected:
// Write out the GOT table.
void
do_write(Output_file*);
private:
// This class represent dynamic relocations that need to be applied by
// gold because we are using TLS relocations in a static link.
class Static_reloc
{
public:
Static_reloc(unsigned int got_offset, unsigned int r_type, Symbol* gsym)
: got_offset_(got_offset), r_type_(r_type), symbol_is_global_(true)
{ this->u_.global.symbol = gsym; }
Static_reloc(unsigned int got_offset, unsigned int r_type,
Sized_relobj<32, big_endian>* relobj, unsigned int index)
: got_offset_(got_offset), r_type_(r_type), symbol_is_global_(false)
{
this->u_.local.relobj = relobj;
this->u_.local.index = index;
}
// Return the GOT offset.
unsigned int
got_offset() const
{ return this->got_offset_; }
// Relocation type.
unsigned int
r_type() const
{ return this->r_type_; }
// Whether the symbol is global or not.
bool
symbol_is_global() const
{ return this->symbol_is_global_; }
// For a relocation against a global symbol, the global symbol.
Symbol*
symbol() const
{
gold_assert(this->symbol_is_global_);
return this->u_.global.symbol;
}
// For a relocation against a local symbol, the defining object.
Sized_relobj<32, big_endian>*
relobj() const
{
gold_assert(!this->symbol_is_global_);
return this->u_.local.relobj;
}
// For a relocation against a local symbol, the local symbol index.
unsigned int
index() const
{
gold_assert(!this->symbol_is_global_);
return this->u_.local.index;
}
private:
// GOT offset of the entry to which this relocation is applied.
unsigned int got_offset_;
// Type of relocation.
unsigned int r_type_;
// Whether this relocation is against a global symbol.
bool symbol_is_global_;
// A global or local symbol.
union
{
struct
{
// For a global symbol, the symbol itself.
Symbol* symbol;
} global;
struct
{
// For a local symbol, the object defining object.
Sized_relobj<32, big_endian>* relobj;
// For a local symbol, the symbol index.
unsigned int index;
} local;
} u_;
};
// Symbol table of the output object.
Symbol_table* symbol_table_;
// Layout of the output object.
Layout* layout_;
// Static relocs to be applied to the GOT.
std::vector<Static_reloc> static_relocs_;
};
// Utilities for manipulating integers of up to 32-bits
namespace utils
@ -2332,7 +2477,7 @@ class Target_arm : public Sized_target<32, big_endian>
optimize_tls_reloc(bool is_final, int r_type);
// Get the GOT section, creating it if necessary.
Output_data_got<32, big_endian>*
Arm_output_data_got<big_endian>*
got_section(Symbol_table*, Layout*);
// Get the GOT PLT section.
@ -2506,7 +2651,7 @@ class Target_arm : public Sized_target<32, big_endian>
Cortex_a8_relocs_info;
// The GOT section.
Output_data_got<32, big_endian>* got_;
Arm_output_data_got<big_endian>* got_;
// The PLT section.
Output_data_plt_arm<big_endian>* plt_;
// The GOT PLT section.
@ -3791,14 +3936,14 @@ Arm_relocate_functions<big_endian>::thm_jump19(
// Get the GOT section, creating it if necessary.
template<bool big_endian>
Output_data_got<32, big_endian>*
Arm_output_data_got<big_endian>*
Target_arm<big_endian>::got_section(Symbol_table* symtab, Layout* layout)
{
if (this->got_ == NULL)
{
gold_assert(symtab != NULL && layout != NULL);
this->got_ = new Output_data_got<32, big_endian>();
this->got_ = new Arm_output_data_got<big_endian>(symtab, layout);
Output_section* os;
os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
@ -5382,6 +5527,7 @@ Arm_output_section<big_endian>::append_text_sections_to_list(
template<bool big_endian>
void
Arm_output_section<big_endian>::fix_exidx_coverage(
Layout* layout,
const Text_section_list& sorted_text_sections,
Symbol_table* symtab)
{
@ -5445,9 +5591,18 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
if (known_input_sections.find(sid) == known_input_sections.end())
{
// This is odd. We have not seen this EXIDX input section before.
// We cannot do fix-up.
gold_error(_("EXIDX section %u of %s is not in EXIDX output section"),
exidx_shndx, exidx_relobj->name().c_str());
// We cannot do fix-up. If we saw a SECTIONS clause in a script,
// issue a warning instead. We assume the user knows what he
// or she is doing. Otherwise, this is an error.
if (layout->script_options()->saw_sections_clause())
gold_warning(_("unwinding may not work because EXIDX input section"
" %u of %s is not in EXIDX output section"),
exidx_shndx, exidx_relobj->name().c_str());
else
gold_error(_("unwinding may not work because EXIDX input section"
" %u of %s is not in EXIDX output section"),
exidx_shndx, exidx_relobj->name().c_str());
exidx_fixup.add_exidx_cantunwind_as_needed();
continue;
}
@ -6273,6 +6428,11 @@ Arm_relobj<big_endian>::do_gc_process_relocs(Symbol_table* symtab,
// First, call base class method to process relocations in this object.
Sized_relobj<32, big_endian>::do_gc_process_relocs(symtab, layout, rd);
// If --gc-sections is not specified, there is nothing more to do.
// This happens when --icf is used but --gc-sections is not.
if (!parameters->options().gc_sections())
return;
unsigned int shnum = this->shnum();
const unsigned int shdr_size = elfcpp::Elf_sizes<32>::shdr_size;
const unsigned char* pshdrs = this->get_view(this->elf_file()->shoff(),
@ -6479,6 +6639,162 @@ Stub_addend_reader<elfcpp::SHT_REL, big_endian>::operator()(
}
}
// Arm_output_data_got methods.
// Add a GOT pair for R_ARM_TLS_GD32. The creates a pair of GOT entries.
// The first one is initialized to be 1, which is the module index for
// the main executable and the second one 0. A reloc of the type
// R_ARM_TLS_DTPOFF32 will be created for the second GOT entry and will
// be applied by gold. GSYM is a global symbol.
//
template<bool big_endian>
void
Arm_output_data_got<big_endian>::add_tls_gd32_with_static_reloc(
unsigned int got_type,
Symbol* gsym)
{
if (gsym->has_got_offset(got_type))
return;
// We are doing a static link. Just mark it as belong to module 1,
// the executable.
unsigned int got_offset = this->add_constant(1);
gsym->set_got_offset(got_type, got_offset);
got_offset = this->add_constant(0);
this->static_relocs_.push_back(Static_reloc(got_offset,
elfcpp::R_ARM_TLS_DTPOFF32,
gsym));
}
// Same as the above but for a local symbol.
template<bool big_endian>
void
Arm_output_data_got<big_endian>::add_tls_gd32_with_static_reloc(
unsigned int got_type,
Sized_relobj<32, big_endian>* object,
unsigned int index)
{
if (object->local_has_got_offset(index, got_type))
return;
// We are doing a static link. Just mark it as belong to module 1,
// the executable.
unsigned int got_offset = this->add_constant(1);
object->set_local_got_offset(index, got_type, got_offset);
got_offset = this->add_constant(0);
this->static_relocs_.push_back(Static_reloc(got_offset,
elfcpp::R_ARM_TLS_DTPOFF32,
object, index));
}
template<bool big_endian>
void
Arm_output_data_got<big_endian>::do_write(Output_file* of)
{
// Call parent to write out GOT.
Output_data_got<32, big_endian>::do_write(of);
// We are done if there is no fix up.
if (this->static_relocs_.empty())
return;
gold_assert(parameters->doing_static_link());
const off_t offset = this->offset();
const section_size_type oview_size =
convert_to_section_size_type(this->data_size());
unsigned char* const oview = of->get_output_view(offset, oview_size);
Output_segment* tls_segment = this->layout_->tls_segment();
gold_assert(tls_segment != NULL);
// The thread pointer $tp points to the TCB, which is followed by the
// TLS. So we need to adjust $tp relative addressing by this amount.
Arm_address aligned_tcb_size =
align_address(ARM_TCB_SIZE, tls_segment->maximum_alignment());
for (size_t i = 0; i < this->static_relocs_.size(); ++i)
{
Static_reloc& reloc(this->static_relocs_[i]);
Arm_address value;
if (!reloc.symbol_is_global())
{
Sized_relobj<32, big_endian>* object = reloc.relobj();
const Symbol_value<32>* psymval =
reloc.relobj()->local_symbol(reloc.index());
// We are doing static linking. Issue an error and skip this
// relocation if the symbol is undefined or in a discarded_section.
bool is_ordinary;
unsigned int shndx = psymval->input_shndx(&is_ordinary);
if ((shndx == elfcpp::SHN_UNDEF)
|| (is_ordinary
&& shndx != elfcpp::SHN_UNDEF
&& !object->is_section_included(shndx)
&& !this->symbol_table_->is_section_folded(object, shndx)))
{
gold_error(_("undefined or discarded local symbol %u from "
" object %s in GOT"),
reloc.index(), reloc.relobj()->name().c_str());
continue;
}
value = psymval->value(object, 0);
}
else
{
const Symbol* gsym = reloc.symbol();
gold_assert(gsym != NULL);
if (gsym->is_forwarder())
gsym = this->symbol_table_->resolve_forwards(gsym);
// We are doing static linking. Issue an error and skip this
// relocation if the symbol is undefined or in a discarded_section
// unless it is a weakly_undefined symbol.
if ((gsym->is_defined_in_discarded_section()
|| gsym->is_undefined())
&& !gsym->is_weak_undefined())
{
gold_error(_("undefined or discarded symbol %s in GOT"),
gsym->name());
continue;
}
if (!gsym->is_weak_undefined())
{
const Sized_symbol<32>* sym =
static_cast<const Sized_symbol<32>*>(gsym);
value = sym->value();
}
else
value = 0;
}
unsigned got_offset = reloc.got_offset();
gold_assert(got_offset < oview_size);
typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
Valtype* wv = reinterpret_cast<Valtype*>(oview + got_offset);
Valtype x;
switch (reloc.r_type())
{
case elfcpp::R_ARM_TLS_DTPOFF32:
x = value;
break;
case elfcpp::R_ARM_TLS_TPOFF32:
x = value + aligned_tcb_size;
break;
default:
gold_unreachable();
}
elfcpp::Swap<32, big_endian>::writeval(wv, x);
}
of->write_output_view(offset, oview_size, oview);
}
// A class to handle the PLT data.
template<bool big_endian>
@ -6764,11 +7080,22 @@ Target_arm<big_endian>::got_mod_index_entry(
if (this->got_mod_index_offset_ == -1U)
{
gold_assert(symtab != NULL && layout != NULL && object != NULL);
Reloc_section* rel_dyn = this->rel_dyn_section(layout);
Output_data_got<32, big_endian>* got = this->got_section(symtab, layout);
unsigned int got_offset = got->add_constant(0);
rel_dyn->add_local(object, 0, elfcpp::R_ARM_TLS_DTPMOD32, got,
got_offset);
Arm_output_data_got<big_endian>* got = this->got_section(symtab, layout);
unsigned int got_offset;
if (!parameters->doing_static_link())
{
got_offset = got->add_constant(0);
Reloc_section* rel_dyn = this->rel_dyn_section(layout);
rel_dyn->add_local(object, 0, elfcpp::R_ARM_TLS_DTPMOD32, got,
got_offset);
}
else
{
// We are doing a static link. Just mark it as belong to module 1,
// the executable.
got_offset = got->add_constant(1);
}
got->add_constant(0);
this->got_mod_index_offset_ = got_offset;
}
@ -7010,7 +7337,7 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
case elfcpp::R_ARM_GOT_PREL:
{
// The symbol requires a GOT entry.
Output_data_got<32, big_endian>* got =
Arm_output_data_got<big_endian>* got =
target->got_section(symtab, layout);
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
if (got->add_local(object, r_sym, GOT_TYPE_STANDARD))
@ -7063,20 +7390,27 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
{
// Create a pair of GOT entries for the module index and
// dtv-relative offset.
Output_data_got<32, big_endian>* got
Arm_output_data_got<big_endian>* got
= target->got_section(symtab, layout);
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
unsigned int shndx = lsym.get_st_shndx();
bool is_ordinary;
shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
if (!is_ordinary)
object->error(_("local symbol %u has bad shndx %u"),
r_sym, shndx);
else
{
object->error(_("local symbol %u has bad shndx %u"),
r_sym, shndx);
break;
}
if (!parameters->doing_static_link())
got->add_local_pair_with_rel(object, r_sym, shndx,
GOT_TYPE_TLS_PAIR,
target->rel_dyn_section(layout),
elfcpp::R_ARM_TLS_DTPMOD32, 0);
else
got->add_tls_gd32_with_static_reloc(GOT_TYPE_TLS_PAIR,
object, r_sym);
}
else
// FIXME: TLS optimization not supported yet.
@ -7101,13 +7435,25 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
layout->set_has_static_tls();
if (optimized_type == tls::TLSOPT_NONE)
{
// Create a GOT entry for the tp-relative offset.
Output_data_got<32, big_endian>* got
= target->got_section(symtab, layout);
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
got->add_local_with_rel(object, r_sym, GOT_TYPE_TLS_OFFSET,
target->rel_dyn_section(layout),
elfcpp::R_ARM_TLS_TPOFF32);
// Create a GOT entry for the tp-relative offset.
Arm_output_data_got<big_endian>* got
= target->got_section(symtab, layout);
unsigned int r_sym =
elfcpp::elf_r_sym<32>(reloc.get_r_info());
if (!parameters->doing_static_link())
got->add_local_with_rel(object, r_sym, GOT_TYPE_TLS_OFFSET,
target->rel_dyn_section(layout),
elfcpp::R_ARM_TLS_TPOFF32);
else if (!object->local_has_got_offset(r_sym,
GOT_TYPE_TLS_OFFSET))
{
got->add_local(object, r_sym, GOT_TYPE_TLS_OFFSET);
unsigned int got_offset =
object->local_got_offset(r_sym, GOT_TYPE_TLS_OFFSET);
got->add_static_reloc(got_offset,
elfcpp::R_ARM_TLS_TPOFF32, object,
r_sym);
}
}
else
// FIXME: TLS optimization not supported yet.
@ -7351,7 +7697,7 @@ Target_arm<big_endian>::Scan::global(Symbol_table* symtab,
case elfcpp::R_ARM_GOT_PREL:
{
// The symbol requires a GOT entry.
Output_data_got<32, big_endian>* got =
Arm_output_data_got<big_endian>* got =
target->got_section(symtab, layout);
if (gsym->final_value_is_known())
got->add_global(gsym, GOT_TYPE_STANDARD);
@ -7408,12 +7754,15 @@ Target_arm<big_endian>::Scan::global(Symbol_table* symtab,
{
// Create a pair of GOT entries for the module index and
// dtv-relative offset.
Output_data_got<32, big_endian>* got
Arm_output_data_got<big_endian>* got
= target->got_section(symtab, layout);
got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
target->rel_dyn_section(layout),
elfcpp::R_ARM_TLS_DTPMOD32,
elfcpp::R_ARM_TLS_DTPOFF32);
if (!parameters->doing_static_link())
got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
target->rel_dyn_section(layout),
elfcpp::R_ARM_TLS_DTPMOD32,
elfcpp::R_ARM_TLS_DTPOFF32);
else
got->add_tls_gd32_with_static_reloc(GOT_TYPE_TLS_PAIR, gsym);
}
else
// FIXME: TLS optimization not supported yet.
@ -7438,12 +7787,21 @@ Target_arm<big_endian>::Scan::global(Symbol_table* symtab,
layout->set_has_static_tls();
if (optimized_type == tls::TLSOPT_NONE)
{
// Create a GOT entry for the tp-relative offset.
Output_data_got<32, big_endian>* got
= target->got_section(symtab, layout);
got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
target->rel_dyn_section(layout),
elfcpp::R_ARM_TLS_TPOFF32);
// Create a GOT entry for the tp-relative offset.
Arm_output_data_got<big_endian>* got
= target->got_section(symtab, layout);
if (!parameters->doing_static_link())
got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
target->rel_dyn_section(layout),
elfcpp::R_ARM_TLS_TPOFF32);
else if (!gsym->has_got_offset(GOT_TYPE_TLS_OFFSET))
{
got->add_global(gsym, GOT_TYPE_TLS_OFFSET);
unsigned int got_offset =
gsym->got_offset(GOT_TYPE_TLS_OFFSET);
got->add_static_reloc(got_offset,
elfcpp::R_ARM_TLS_TPOFF32, gsym);
}
}
else
// FIXME: TLS optimization not supported yet.
@ -8233,10 +8591,11 @@ Target_arm<big_endian>::Relocate::relocate_tls(
const Sized_symbol<32>* gsym,
const Symbol_value<32>* psymval,
unsigned char* view,
elfcpp::Elf_types<32>::Elf_Addr,
elfcpp::Elf_types<32>::Elf_Addr address,
section_size_type /*view_size*/ )
{
typedef Arm_relocate_functions<big_endian> ArmRelocFuncs;
typedef Relocate_functions<32, big_endian> RelocFuncs;
Output_segment* tls_segment = relinfo->layout->tls_segment();
const Sized_relobj<32, big_endian>* object = relinfo->object;
@ -8268,9 +8627,12 @@ Target_arm<big_endian>::Relocate::relocate_tls(
}
if (optimized_type == tls::TLSOPT_NONE)
{
// Relocate the field with the offset of the pair of GOT
// entries.
Relocate_functions<32, big_endian>::rel32(view, got_offset);
Arm_address got_entry =
target->got_plt_section()->address() + got_offset;
// Relocate the field with the PC relative offset of the pair of
// GOT entries.
RelocFuncs::pcrel32(view, got_entry, address);
return ArmRelocFuncs::STATUS_OKAY;
}
}
@ -8284,13 +8646,18 @@ Target_arm<big_endian>::Relocate::relocate_tls(
unsigned int got_offset;
got_offset = (target->got_mod_index_entry(NULL, NULL, NULL)
- target->got_size());
Relocate_functions<32, big_endian>::rel32(view, got_offset);
Arm_address got_entry =
target->got_plt_section()->address() + got_offset;
// Relocate the field with the PC relative offset of the pair of
// GOT entries.
RelocFuncs::pcrel32(view, got_entry, address);
return ArmRelocFuncs::STATUS_OKAY;
}
break;
case elfcpp::R_ARM_TLS_LDO32: // Alternate local-dynamic
Relocate_functions<32, big_endian>::rel32(view, value);
RelocFuncs::rel32(view, value);
return ArmRelocFuncs::STATUS_OKAY;
case elfcpp::R_ARM_TLS_IE32: // Initial-exec
@ -8311,9 +8678,15 @@ Target_arm<big_endian>::Relocate::relocate_tls(
gold_assert(object->local_has_got_offset(r_sym, got_type));
got_offset = object->local_got_offset(r_sym, got_type);
}
// All GOT offsets are relative to the end of the GOT.
got_offset -= target->got_size();
Relocate_functions<32, big_endian>::rel32(view, got_offset);
Arm_address got_entry =
target->got_plt_section()->address() + got_offset;
// Relocate the field with the PC relative offset of the GOT entry.
RelocFuncs::pcrel32(view, got_entry, address);
return ArmRelocFuncs::STATUS_OKAY;
}
break;
@ -8324,8 +8697,13 @@ Target_arm<big_endian>::Relocate::relocate_tls(
if (!parameters->options().shared())
{
gold_assert(tls_segment != NULL);
value = tls_segment->memsz() - value;
Relocate_functions<32, false>::rel32(view, value);
// $tp points to the TCB, which is followed by the TLS, so we
// need to add TCB size to the offset.
Arm_address aligned_tcb_size =
align_address(ARM_TCB_SIZE, tls_segment->maximum_alignment());
RelocFuncs::rel32(view, value + aligned_tcb_size);
}
return ArmRelocFuncs::STATUS_OKAY;
@ -10413,7 +10791,7 @@ Target_arm<big_endian>::fix_exidx_coverage(
arm_output_section->append_text_sections_to_list(&sorted_text_sections);
}
exidx_section->fix_exidx_coverage(sorted_text_sections, symtab);
exidx_section->fix_exidx_coverage(layout, sorted_text_sections, symtab);
}
Target_selector_arm<false> target_selector_arm;

View file

@ -3569,9 +3569,9 @@ const Layout::Section_name_mapping Layout::section_name_mapping[] =
MAPPING_INIT(".gnu.linkonce.lr.", ".lrodata"),
MAPPING_INIT(".gnu.linkonce.l.", ".ldata"),
MAPPING_INIT(".gnu.linkonce.lb.", ".lbss"),
MAPPING_INIT(".ARM.extab.", ".ARM.extab"),
MAPPING_INIT(".ARM.extab", ".ARM.extab"),
MAPPING_INIT(".gnu.linkonce.armextab.", ".ARM.extab"),
MAPPING_INIT(".ARM.exidx.", ".ARM.exidx"),
MAPPING_INIT(".ARM.exidx", ".ARM.exidx"),
MAPPING_INIT(".gnu.linkonce.armexidx.", ".ARM.exidx"),
};
#undef MAPPING_INIT