{
public:
Relocate()
- : skip_call_tls_get_addr_(false)
+ : skip_call_tls_get_addr_(false), saw_tls_block_reloc_(false)
{ }
~Relocate()
// This is set if we should skip the next reloc, which should be a
// PLT32 reloc against ___tls_get_addr.
bool skip_call_tls_get_addr_;
+
+ // This is set if we see a relocation which could load the address
+ // of the TLS block. Whether we see such a relocation determines
+ // how we handle the R_X86_64_DTPOFF32 relocation, which is used
+ // in debugging sections.
+ bool saw_tls_block_reloc_;
};
// A class which returns the size required for a relocation type,
this->got_ = new Output_data_got<64, false>();
- layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
- elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
- this->got_);
+ Output_section* os;
+ os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
+ (elfcpp::SHF_ALLOC
+ | elfcpp::SHF_WRITE),
+ this->got_);
+ os->set_is_relro();
// The old GNU linker creates a .got.plt section. We just
// create another set of data in the .got section. Note that we
// always create a PLT if we create a GOT, although the PLT
// might be empty.
- this->got_plt_ = new Output_data_space(8);
- layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
- elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
- this->got_plt_);
+ this->got_plt_ = new Output_data_space(8, "** GOT PLT");
+ os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
+ (elfcpp::SHF_ALLOC
+ | elfcpp::SHF_WRITE),
+ this->got_plt_);
+ os->set_is_relro();
// The first three entries are reserved.
this->got_plt_->set_current_data_size(3 * 8);
void
do_adjust_output_section(Output_section* os);
+ // Write to a map file.
+ void
+ do_print_to_mapfile(Mapfile* mapfile) const
+ { mapfile->print_output_data(this, _("** PLT")); }
+
private:
// The size of an entry in the PLT.
static const int plt_entry_size = 16;
unsigned char* pov = oview;
// The base address of the .plt section.
- elfcpp::Elf_types<32>::Elf_Addr plt_address = this->address();
+ elfcpp::Elf_types<64>::Elf_Addr plt_address = this->address();
// The base address of the .got section.
- elfcpp::Elf_types<32>::Elf_Addr got_base = this->got_->address();
+ elfcpp::Elf_types<64>::Elf_Addr got_base = this->got_->address();
// The base address of the PLT portion of the .got section,
// which is where the GOT pointer will point, and where the
// three reserved GOT entries are located.
- elfcpp::Elf_types<32>::Elf_Addr got_address = this->got_plt_->address();
+ elfcpp::Elf_types<64>::Elf_Addr got_address = this->got_plt_->address();
memcpy(pov, first_plt_entry, plt_entry_size);
// We do a jmp relative to the PC at the end of this instruction.
- elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_address + 8
- - (plt_address + 6));
- elfcpp::Swap<32, false>::writeval(pov + 8, got_address + 16
- - (plt_address + 12));
+ elfcpp::Swap_unaligned<32, false>::writeval(pov + 2,
+ (got_address + 8
+ - (plt_address + 6)));
+ elfcpp::Swap<32, false>::writeval(pov + 8,
+ (got_address + 16
+ - (plt_address + 12)));
pov += plt_entry_size;
unsigned char* got_pov = got_view;
switch (r_type)
{
case elfcpp::R_X86_64_TLSGD: // Global-dynamic
+ this->saw_tls_block_reloc_ = true;
if (optimized_type == tls::TLSOPT_TO_LE)
{
gold_assert(tls_segment != NULL);
case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url)
case elfcpp::R_X86_64_TLSDESC_CALL:
+ this->saw_tls_block_reloc_ = true;
if (optimized_type == tls::TLSOPT_TO_LE)
{
gold_assert(tls_segment != NULL);
break;
case elfcpp::R_X86_64_TLSLD: // Local-dynamic
+ this->saw_tls_block_reloc_ = true;
if (optimized_type == tls::TLSOPT_TO_LE)
{
gold_assert(tls_segment != NULL);
case elfcpp::R_X86_64_DTPOFF32:
gold_assert(tls_segment != NULL);
if (optimized_type == tls::TLSOPT_TO_LE)
- value -= tls_segment->memsz();
+ {
+ // This relocation type is used in debugging information.
+ // In that case we need to not optimize the value. If we
+ // haven't seen a TLSLD reloc, then we assume we should not
+ // optimize this reloc.
+ if (this->saw_tls_block_reloc_)
+ value -= tls_segment->memsz();
+ }
Relocate_functions<64, false>::rela32(view, value, 0);
break;
case elfcpp::R_X86_64_DTPOFF64:
gold_assert(tls_segment != NULL);
if (optimized_type == tls::TLSOPT_TO_LE)
- value -= tls_segment->memsz();
+ {
+ // See R_X86_64_DTPOFF32, just above, for why we test this.
+ if (this->saw_tls_block_reloc_)
+ value -= tls_segment->memsz();
+ }
Relocate_functions<64, false>::rela64(view, value, 0);
break;