* mapfile.cc: New file.
[deliverable/binutils-gdb.git] / gold / x86_64.cc
index 6459e500827b8962f65fb981cd3f1b94db7b8c95..356505c18355acd0b91bc34f989f88e9f18d890b 100644 (file)
@@ -197,7 +197,7 @@ class Target_x86_64 : public Sized_target<64, false>
   {
    public:
     Relocate()
-      : skip_call_tls_get_addr_(false)
+      : skip_call_tls_get_addr_(false), saw_tls_block_reloc_(false)
     { }
 
     ~Relocate()
@@ -288,6 +288,12 @@ class Target_x86_64 : public Sized_target<64, false>
     // 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,
@@ -429,18 +435,23 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout)
 
       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);
@@ -515,6 +526,11 @@ class Output_data_plt_x86_64 : public Output_section_data
   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;
@@ -672,20 +688,22 @@ Output_data_plt_x86_64::do_write(Output_file* of)
   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;
@@ -1895,6 +1913,7 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
   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);
@@ -1945,6 +1964,7 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
 
     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);
@@ -1998,6 +2018,7 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
       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);
@@ -2024,14 +2045,25 @@ Target_x86_64::Relocate::relocate_tls(const Relocate_info<64, false>* relinfo,
     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;
 
This page took 0.03263 seconds and 4 git commands to generate.