From Craig Silverstein: add tls.h, use it in i386.cc.
authorIan Lance Taylor <iant@google.com>
Mon, 8 Oct 2007 05:12:59 +0000 (05:12 +0000)
committerIan Lance Taylor <iant@google.com>
Mon, 8 Oct 2007 05:12:59 +0000 (05:12 +0000)
gold/Makefile.am
gold/Makefile.in
gold/i386.cc
gold/po/POTFILES.in
gold/po/gold.pot
gold/tls.h [new file with mode: 0644]

index 87bde55..e9508de 100644 (file)
@@ -75,6 +75,7 @@ HFILES = \
        target.h \
        target-reloc.h \
        target-select.h \
+       tls.h \
        workqueue.h
 
 YFILES = \
index 13a3536..9d9ff8c 100644 (file)
@@ -326,6 +326,7 @@ HFILES = \
        target.h \
        target-reloc.h \
        target-select.h \
+       tls.h \
        workqueue.h
 
 YFILES = \
index 033a9b9..ce4d961 100644 (file)
@@ -35,6 +35,7 @@
 #include "target.h"
 #include "target-reloc.h"
 #include "target-select.h"
+#include "tls.h"
 
 namespace
 {
@@ -112,6 +113,13 @@ class Target_i386 : public Sized_target<32, false>
           unsigned int data_shndx,
           const elfcpp::Rel<32, false>& reloc, unsigned int r_type,
           Symbol* gsym);
+
+    static void
+    unsupported_reloc_local(Sized_relobj<32, false>*, unsigned int r_type);
+
+    static void
+    unsupported_reloc_global(Sized_relobj<32, false>*, unsigned int r_type,
+                            Symbol*);
   };
 
   // The class which implements relocation.
@@ -180,16 +188,6 @@ class Target_i386 : public Sized_target<32, false>
                 unsigned char* view,
                 off_t view_size);
 
-    // Check the range for a TLS relocation.
-    static inline void
-    check_range(const Relocate_info<32, false>*, size_t relnum,
-               const elfcpp::Rel<32, false>&, off_t, off_t);
-
-    // Check the validity of a TLS relocation.  This is like assert.
-    static inline void
-    check_tls(const Relocate_info<32, false>*, size_t relnum,
-             const elfcpp::Rel<32, false>&, bool);
-
     // We need to keep track of which type of local dynamic relocation
     // we have seen, so that we can optimize R_386_TLS_LDO_32 correctly.
     enum Local_dynamic_type
@@ -209,7 +207,7 @@ class Target_i386 : public Sized_target<32, false>
 
   // Adjust TLS relocation type based on the options and whether this
   // is a local symbol.
-  static unsigned int
+  static tls::Tls_optimization
   optimize_tls_reloc(bool is_final, int r_type);
 
   // Get the GOT section, creating it if necessary.
@@ -667,13 +665,13 @@ Target_i386::copy_reloc(const General_options* options,
 // symbol.  IS_FINAL is true if the final address of this symbol is
 // known at link time.
 
-unsigned int
+tls::Tls_optimization
 Target_i386::optimize_tls_reloc(bool is_final, int r_type)
 {
   // If we are generating a shared library, then we can't do anything
   // in the linker.
   if (parameters->output_is_shared())
-    return r_type;
+    return tls::TLSOPT_NONE;
 
   switch (r_type)
     {
@@ -685,20 +683,18 @@ Target_i386::optimize_tls_reloc(bool is_final, int r_type)
       // we can convert this to Initial-Exec.  If we also know that
       // this is a local symbol, we can further switch to Local-Exec.
       if (is_final)
-       return elfcpp::R_386_TLS_LE_32;
-      return elfcpp::R_386_TLS_IE_32;
+       return tls::TLSOPT_TO_LE;
+      return tls::TLSOPT_TO_IE;
 
     case elfcpp::R_386_TLS_LDM:
       // This is Local-Dynamic, which refers to a local symbol in the
       // dynamic TLS block.  Since we know that we generating an
       // executable, we can switch to Local-Exec.
-      return elfcpp::R_386_TLS_LE_32;
+      return tls::TLSOPT_TO_LE;
 
     case elfcpp::R_386_TLS_LDO_32:
-      // Another type of Local-Dynamic relocation.  We return a
-      // different value as we need to negate the thread segment
-      // offset.  FIXME: Returning reloc types makes no sense.
-      return elfcpp::R_386_TLS_LE;
+      // Another type of Local-Dynamic relocation.
+      return tls::TLSOPT_TO_LE;
 
     case elfcpp::R_386_TLS_IE:
     case elfcpp::R_386_TLS_GOTIE:
@@ -708,20 +704,30 @@ Target_i386::optimize_tls_reloc(bool is_final, int r_type)
       // local symbol, we can switch to Local-Exec, which links the
       // thread offset into the instruction.
       if (is_final)
-       return elfcpp::R_386_TLS_LE_32;
-      return r_type;
+       return tls::TLSOPT_TO_LE;
+      return tls::TLSOPT_NONE;
 
     case elfcpp::R_386_TLS_LE:
     case elfcpp::R_386_TLS_LE_32:
       // When we already have Local-Exec, there is nothing further we
       // can do.
-      return r_type;
+      return tls::TLSOPT_NONE;
 
     default:
       gold_unreachable();
     }
 }
 
+// Report an unsupported relocation against a local symbol.
+
+void
+Target_i386::Scan::unsupported_reloc_local(Sized_relobj<32, false>* object,
+                                          unsigned int r_type)
+{
+  fprintf(stderr, _("%s: %s: unsupported reloc %u against local symbol\n"),
+         program_name, object->name().c_str(), r_type);
+}
+
 // Scan a relocation for a local symbol.
 
 inline void
@@ -761,12 +767,12 @@ Target_i386::Scan::local(const General_options&,
       target->got_section(symtab, layout);
       break;
 
+      // These are relocations which should only be seen by the
+      // dynamic linker, and should never be seen here.
     case elfcpp::R_386_COPY:
     case elfcpp::R_386_GLOB_DAT:
     case elfcpp::R_386_JUMP_SLOT:
     case elfcpp::R_386_RELATIVE:
-      // These are outstanding tls relocs, which are unexpected when
-      // linking.
     case elfcpp::R_386_TLS_TPOFF:
     case elfcpp::R_386_TLS_DTPMOD32:
     case elfcpp::R_386_TLS_DTPOFF32:
@@ -777,7 +783,7 @@ Target_i386::Scan::local(const General_options&,
       gold_exit(false);
       break;
 
-      // These are initial tls relocs, which are expected when
+      // These are initial TLS relocs, which are expected when
       // linking.
     case elfcpp::R_386_TLS_IE:
     case elfcpp::R_386_TLS_GOTIE:
@@ -791,8 +797,8 @@ Target_i386::Scan::local(const General_options&,
     case elfcpp::R_386_TLS_DESC_CALL:
       {
        bool output_is_shared = parameters->output_is_shared();
-       r_type = Target_i386::optimize_tls_reloc(!output_is_shared,
-                                                r_type);
+       const tls::Tls_optimization optimized_type
+            = Target_i386::optimize_tls_reloc(!output_is_shared, r_type);
        switch (r_type)
          {
          case elfcpp::R_386_TLS_LE:
@@ -802,20 +808,36 @@ Target_i386::Scan::local(const General_options&,
            gold_assert(!output_is_shared);
            break;
 
+         case elfcpp::R_386_TLS_IE:
+         case elfcpp::R_386_TLS_IE_32:
+         case elfcpp::R_386_TLS_GOTIE:
+           // FIXME: If not relaxing to LE, we need to generate a
+           // TPOFF or TPOFF32 reloc.
+           if (optimized_type != tls::TLSOPT_TO_LE)
+             unsupported_reloc_local(object, r_type);
+           break;
+
          case elfcpp::R_386_TLS_LDM:
+           // FIXME: If not relaxing to LE, we need to generate a
+           // DTPMOD32 reloc.
+           if (optimized_type != tls::TLSOPT_TO_LE)
+             unsupported_reloc_local(object, r_type);
+           break;
+
          case elfcpp::R_386_TLS_LDO_32:
            break;
 
-         case elfcpp::R_386_TLS_IE:
-         case elfcpp::R_386_TLS_GOTIE:
          case elfcpp::R_386_TLS_GD:
-         case elfcpp::R_386_TLS_IE_32:
          case elfcpp::R_386_TLS_GOTDESC:
          case elfcpp::R_386_TLS_DESC_CALL:
-           fprintf(stderr,
-                   _("%s: %s: unsupported reloc %u against local symbol\n"),
-                   program_name, object->name().c_str(), r_type);
+           // FIXME: If not relaxing to LE, we need to generate
+           // DTPMOD32 and DTPOFF32 relocs.
+           if (optimized_type != tls::TLSOPT_TO_LE)
+             unsupported_reloc_local(object, r_type);
            break;
+
+         default:
+           gold_unreachable();
          }
       }
       break;
@@ -833,12 +855,23 @@ Target_i386::Scan::local(const General_options&,
     case elfcpp::R_386_TLS_LDM_POP:
     case elfcpp::R_386_USED_BY_INTEL_200:
     default:
-      fprintf(stderr, _("%s: %s: unsupported reloc %u against local symbol\n"),
-             program_name, object->name().c_str(), r_type);
+      unsupported_reloc_local(object, r_type);
       break;
     }
 }
 
+// Report an unsupported relocation against a global symbol.
+
+void
+Target_i386::Scan::unsupported_reloc_global(Sized_relobj<32, false>* object,
+                                           unsigned int r_type,
+                                           Symbol* gsym)
+{
+  fprintf(stderr,
+         _("%s: %s: unsupported reloc %u against global symbol %s\n"),
+         program_name, object->name().c_str(), r_type, gsym->name());
+}
+
 // Scan a relocation for a global symbol.
 
 inline void
@@ -928,12 +961,12 @@ Target_i386::Scan::global(const General_options& options,
       target->got_section(symtab, layout);
       break;
 
+      // These are relocations which should only be seen by the
+      // dynamic linker, and should never be seen here.
     case elfcpp::R_386_COPY:
     case elfcpp::R_386_GLOB_DAT:
     case elfcpp::R_386_JUMP_SLOT:
     case elfcpp::R_386_RELATIVE:
-      // These are outstanding tls relocs, which are unexpected when
-      // linking.
     case elfcpp::R_386_TLS_TPOFF:
     case elfcpp::R_386_TLS_DTPMOD32:
     case elfcpp::R_386_TLS_DTPOFF32:
@@ -958,7 +991,8 @@ Target_i386::Scan::global(const General_options& options,
     case elfcpp::R_386_TLS_DESC_CALL:
       {
        const bool is_final = gsym->final_value_is_known();
-       r_type = Target_i386::optimize_tls_reloc(is_final, r_type);
+       const tls::Tls_optimization optimized_type
+            = Target_i386::optimize_tls_reloc(is_final, r_type);
        switch (r_type)
          {
          case elfcpp::R_386_TLS_LE:
@@ -968,22 +1002,36 @@ Target_i386::Scan::global(const General_options& options,
            gold_assert(!parameters->output_is_shared());
            break;
 
+         case elfcpp::R_386_TLS_IE:
+         case elfcpp::R_386_TLS_IE_32:
+         case elfcpp::R_386_TLS_GOTIE:
+           // FIXME: If not relaxing to LE, we need to generate a
+           // TPOFF or TPOFF32 reloc.
+           if (optimized_type != tls::TLSOPT_TO_LE)
+             unsupported_reloc_global(object, r_type, gsym);
+           break;
+
          case elfcpp::R_386_TLS_LDM:
+           // FIXME: If not relaxing to LE, we need to generate a
+           // DTPMOD32 reloc.
+           if (optimized_type != tls::TLSOPT_TO_LE)
+             unsupported_reloc_global(object, r_type, gsym);
+           break;
+
          case elfcpp::R_386_TLS_LDO_32:
            break;
 
-         case elfcpp::R_386_TLS_IE:
-         case elfcpp::R_386_TLS_GOTIE:
          case elfcpp::R_386_TLS_GD:
-         case elfcpp::R_386_TLS_IE_32:
          case elfcpp::R_386_TLS_GOTDESC:
          case elfcpp::R_386_TLS_DESC_CALL:
-           fprintf(stderr,
-                   _("%s: %s: unsupported reloc %u "
-                     "against global symbol %s\n"),
-                   program_name, object->name().c_str(), r_type,
-                   gsym->name());
+           // FIXME: If not relaxing to LE, we need to generate
+           // DTPMOD32 and DTPOFF32 relocs.
+           if (optimized_type != tls::TLSOPT_TO_LE)
+             unsupported_reloc_global(object, r_type, gsym);
            break;
+
+         default:
+           gold_unreachable();
          }
       }
       break;
@@ -999,9 +1047,7 @@ Target_i386::Scan::global(const General_options& options,
     case elfcpp::R_386_TLS_LDM_POP:
     case elfcpp::R_386_USED_BY_INTEL_200:
     default:
-      fprintf(stderr,
-             _("%s: %s: unsupported reloc %u against global symbol %s\n"),
-             program_name, object->name().c_str(), r_type, gsym->name());
+      unsupported_reloc_global(object, r_type, gsym);
       break;
     }
 }
@@ -1279,8 +1325,8 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
   const bool is_final = (gsym == NULL
                         ? !parameters->output_is_shared()
                         : gsym->final_value_is_known());
-  const unsigned int opt_r_type =
-    Target_i386::optimize_tls_reloc(is_final, r_type);
+  const tls::Tls_optimization optimized_type
+      = Target_i386::optimize_tls_reloc(is_final, r_type);
   switch (r_type)
     {
     case elfcpp::R_386_TLS_LE_32:
@@ -1296,14 +1342,14 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
     case elfcpp::R_386_TLS_IE:
     case elfcpp::R_386_TLS_GOTIE:
     case elfcpp::R_386_TLS_IE_32:
-      if (opt_r_type == elfcpp::R_386_TLS_LE_32)
+      if (optimized_type == tls::TLSOPT_TO_LE)
        {
          Target_i386::Relocate::tls_ie_to_le(relinfo, relnum, tls_segment,
                                              rel, r_type, value, view,
                                              view_size);
          break;
        }
-      fprintf(stderr, _("%s: %s: unsupported reloc type %u\n"),
+      fprintf(stderr, _("%s: %s: unsupported reloc %u\n"),
              program_name,
              relinfo->location(relnum, rel.get_r_offset()).c_str(),
              r_type);
@@ -1311,7 +1357,7 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
       break;
 
     case elfcpp::R_386_TLS_GD:
-      if (opt_r_type == elfcpp::R_386_TLS_LE_32)
+      if (optimized_type == tls::TLSOPT_TO_LE)
        {
          this->tls_gd_to_le(relinfo, relnum, tls_segment,
                             rel, r_type, value, view,
@@ -1335,7 +1381,7 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
          gold_exit(false);
        }
       this->local_dynamic_type_ = LOCAL_DYNAMIC_GNU;
-      if (opt_r_type == elfcpp::R_386_TLS_LE_32)
+      if (optimized_type == tls::TLSOPT_TO_LE)
        {
          this->tls_ld_to_le(relinfo, relnum, tls_segment, rel, r_type,
                             value, view, view_size);
@@ -1352,7 +1398,7 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
       // This reloc can appear in debugging sections, in which case we
       // won't see the TLS_LDM reloc.  The local_dynamic_type field
       // tells us this.
-      if (opt_r_type == elfcpp::R_386_TLS_LDO_32
+      if (optimized_type != tls::TLSOPT_TO_LE
          || this->local_dynamic_type_ == LOCAL_DYNAMIC_NONE)
        value = value - tls_segment->vaddr();
       else if (this->local_dynamic_type_ == LOCAL_DYNAMIC_GNU)
@@ -1394,8 +1440,8 @@ Target_i386::Relocate::tls_ie_to_le(const Relocate_info<32, false>* relinfo,
       // movl %gs:XX,%eax  ==>  movl $YY,%eax
       // movl %gs:XX,%reg  ==>  movl $YY,%reg
       // addl %gs:XX,%reg  ==>  addl $YY,%reg
-      Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, -1);
-      Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, 4);
+      tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -1);
+      tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 4);
 
       unsigned char op1 = view[-1];
       if (op1 == 0xa1)
@@ -1405,28 +1451,27 @@ Target_i386::Relocate::tls_ie_to_le(const Relocate_info<32, false>* relinfo,
        }
       else
        {
-         Target_i386::Relocate::check_range(relinfo, relnum, rel,
-                                            view_size, -2);
+         tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -2);
 
          unsigned char op2 = view[-2];
          if (op2 == 0x8b)
            {
              // movl XX,%reg  ==>  movl $YY,%reg
-             Target_i386::Relocate::check_tls(relinfo, relnum, rel,
-                                              (op1 & 0xc7) == 0x05);
+             tls::check_tls(relinfo, relnum, rel.get_r_offset(),
+                             (op1 & 0xc7) == 0x05);
              view[-2] = 0xc7;
              view[-1] = 0xc0 | ((op1 >> 3) & 7);
            }
          else if (op2 == 0x03)
            {
              // addl XX,%reg  ==>  addl $YY,%reg
-             Target_i386::Relocate::check_tls(relinfo, relnum, rel,
-                                              (op1 & 0xc7) == 0x05);
+             tls::check_tls(relinfo, relnum, rel.get_r_offset(),
+                             (op1 & 0xc7) == 0x05);
              view[-2] = 0x81;
              view[-1] = 0xc0 | ((op1 >> 3) & 7);
            }
          else
-           Target_i386::Relocate::check_tls(relinfo, relnum, rel, 0);
+           tls::check_tls(relinfo, relnum, rel.get_r_offset(), 0);
        }
     }
   else
@@ -1434,13 +1479,13 @@ Target_i386::Relocate::tls_ie_to_le(const Relocate_info<32, false>* relinfo,
       // subl %gs:XX(%reg1),%reg2  ==>  subl $YY,%reg2
       // movl %gs:XX(%reg1),%reg2  ==>  movl $YY,%reg2
       // addl %gs:XX(%reg1),%reg2  ==>  addl $YY,$reg2
-      Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, -2);
-      Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, 4);
+      tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -2);
+      tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 4);
 
       unsigned char op1 = view[-1];
       unsigned char op2 = view[-2];
-      Target_i386::Relocate::check_tls(relinfo, relnum, rel,
-                                      (op1 & 0xc0) == 0x80 && (op1 & 7) != 4);
+      tls::check_tls(relinfo, relnum, rel.get_r_offset(),
+                     (op1 & 0xc0) == 0x80 && (op1 & 7) != 4);
       if (op2 == 0x8b)
        {
          // movl %gs:XX(%reg1),%reg2  ==>  movl $YY,%reg2
@@ -1460,7 +1505,7 @@ Target_i386::Relocate::tls_ie_to_le(const Relocate_info<32, false>* relinfo,
          view[-1] = 0xc0 | ((op1 >> 3) & 7);
        }
       else
-       Target_i386::Relocate::check_tls(relinfo, relnum, rel, 0);
+       tls::check_tls(relinfo, relnum, rel.get_r_offset(), 0);
     }
 
   value = tls_segment->vaddr() + tls_segment->memsz() - value;
@@ -1488,33 +1533,30 @@ Target_i386::Relocate::tls_gd_to_le(const Relocate_info<32, false>* relinfo,
   // leal foo(%reg),%eax; call ___tls_get_addr
   //  ==> movl %gs:0,%eax; subl $foo@tpoff,%eax
 
-  Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, -2);
-  Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, 9);
+  tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -2);
+  tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 9);
 
   unsigned char op1 = view[-1];
   unsigned char op2 = view[-2];
 
-  Target_i386::Relocate::check_tls(relinfo, relnum, rel,
-                                  op2 == 0x8d || op2 == 0x04);
-  Target_i386::Relocate::check_tls(relinfo, relnum, rel,
-                                  view[4] == 0xe8);
+  tls::check_tls(relinfo, relnum, rel.get_r_offset(),
+                 op2 == 0x8d || op2 == 0x04);
+  tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[4] == 0xe8);
 
   int roff = 5;
 
   if (op2 == 0x04)
     {
-      Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, -3);
-      Target_i386::Relocate::check_tls(relinfo, relnum, rel,
-                                      view[-3] == 0x8d);
-      Target_i386::Relocate::check_tls(relinfo, relnum, rel,
-                                      ((op1 & 0xc7) == 0x05
-                                       && op1 != (4 << 3)));
+      tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -3);
+      tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[-3] == 0x8d);
+      tls::check_tls(relinfo, relnum, rel.get_r_offset(),
+                     ((op1 & 0xc7) == 0x05 && op1 != (4 << 3)));
       memcpy(view - 3, "\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12);
     }
   else
     {
-      Target_i386::Relocate::check_tls(relinfo, relnum, rel,
-                                      (op1 & 0xf8) == 0x80 && (op1 & 7) != 4);
+      tls::check_tls(relinfo, relnum, rel.get_r_offset(),
+                     (op1 & 0xf8) == 0x80 && (op1 & 7) != 4);
       if (static_cast<off_t>(rel.get_r_offset() + 9) < view_size
           && view[9] == 0x90)
        {
@@ -1553,15 +1595,14 @@ Target_i386::Relocate::tls_ld_to_le(const Relocate_info<32, false>* relinfo,
   // leal foo(%reg), %eax; call ___tls_get_addr
   // ==> movl %gs:0,%eax; nop; leal 0(%esi,1),%esi
 
-  Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, -2);
-  Target_i386::Relocate::check_range(relinfo, relnum, rel, view_size, 9);
+  tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, -2);
+  tls::check_range(relinfo, relnum, rel.get_r_offset(), view_size, 9);
 
   // FIXME: Does this test really always pass?
-  Target_i386::Relocate::check_tls(relinfo, relnum, rel,
-                                  view[-2] == 0x8d && view[-1] == 0x83);
+  tls::check_tls(relinfo, relnum, rel.get_r_offset(),
+                 view[-2] == 0x8d && view[-1] == 0x83);
 
-  Target_i386::Relocate::check_tls(relinfo, relnum, rel,
-                                  view[4] == 0xe8);
+  tls::check_tls(relinfo, relnum, rel.get_r_offset(), view[4] == 0xe8);
 
   memcpy(view - 2, "\x65\xa1\0\0\0\0\x90\x8d\x74\x26\0", 11);
 
@@ -1570,42 +1611,6 @@ Target_i386::Relocate::tls_ld_to_le(const Relocate_info<32, false>* relinfo,
   this->skip_call_tls_get_addr_ = true;
 }
 
-// Check the range for a TLS relocation.
-
-inline void
-Target_i386::Relocate::check_range(const Relocate_info<32, false>* relinfo,
-                                  size_t relnum,
-                                  const elfcpp::Rel<32, false>& rel,
-                                  off_t view_size, off_t off)
-{
-  off_t offset = rel.get_r_offset() + off;
-  if (offset < 0 || offset > view_size)
-    {
-      fprintf(stderr, _("%s: %s: TLS relocation out of range\n"),
-             program_name,
-             relinfo->location(relnum, rel.get_r_offset()).c_str());
-      gold_exit(false);
-    }
-}
-
-// Check the validity of a TLS relocation.  This is like assert.
-
-inline void
-Target_i386::Relocate::check_tls(const Relocate_info<32, false>* relinfo,
-                                size_t relnum,
-                                const elfcpp::Rel<32, false>& rel,
-                                bool valid)
-{
-  if (!valid)
-    {
-      fprintf(stderr,
-             _("%s: %s: TLS relocation against invalid instruction\n"),
-             program_name,
-             relinfo->location(relnum, rel.get_r_offset()).c_str());
-      gold_exit(false);
-    }
-}
-
 // Relocate section data.
 
 void
index 9628afa..a65d3a5 100644 (file)
@@ -46,6 +46,7 @@ target.h
 target-reloc.h
 target-select.cc
 target-select.h
+tls.h
 version.cc
 workqueue.cc
 workqueue.h
index cf5aea9..20bada8 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2007-10-07 11:04-0700\n"
+"POT-Creation-Date: 2007-10-07 22:11-0700\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -270,68 +270,53 @@ msgid "pthread_cond_signal failed"
 msgstr ""
 
 #. FIXME: This needs to specify the location somehow.
-#: i386.cc:131 x86_64.cc:146
+#: i386.cc:139 x86_64.cc:146
 #, c-format
 msgid "%s: missing expected TLS relocation\n"
 msgstr ""
 
-#: i386.cc:775 i386.cc:942 i386.cc:1210 x86_64.cc:737 x86_64.cc:898
-#: x86_64.cc:1215
+#: i386.cc:727 x86_64.cc:766 x86_64.cc:782
 #, c-format
-msgid "%s: %s: unexpected reloc %u in object file\n"
+msgid "%s: %s: unsupported reloc %u against local symbol\n"
 msgstr ""
 
-#: i386.cc:816 i386.cc:836 x86_64.cc:766 x86_64.cc:782
+#: i386.cc:781 i386.cc:975 i386.cc:1256 x86_64.cc:737 x86_64.cc:898
+#: x86_64.cc:1215
 #, c-format
-msgid "%s: %s: unsupported reloc %u against local symbol\n"
+msgid "%s: %s: unexpected reloc %u in object file\n"
 msgstr ""
 
-#: i386.cc:982 i386.cc:1003 x86_64.cc:927 x86_64.cc:940
+#: i386.cc:871 x86_64.cc:927 x86_64.cc:940
 #, c-format
 msgid "%s: %s: unsupported reloc %u against global symbol %s\n"
 msgstr ""
 
-#: i386.cc:1026
+#: i386.cc:1072
 #, c-format
 msgid "%s: %s: unsupported RELA reloc section\n"
 msgstr ""
 
-#: i386.cc:1116 x86_64.cc:1053
+#: i386.cc:1162 x86_64.cc:1053
 #, c-format
 msgid "%s: %s: missing expected TLS relocation\n"
 msgstr ""
 
-#: i386.cc:1244 i386.cc:1321 i386.cc:1344 i386.cc:1367 x86_64.cc:1237
-#: x86_64.cc:1307 x86_64.cc:1315
+#: i386.cc:1290 i386.cc:1352 i386.cc:1367 i386.cc:1390 i386.cc:1413
+#: x86_64.cc:1237 x86_64.cc:1307 x86_64.cc:1315
 #, c-format
 msgid "%s: %s: unsupported reloc %u\n"
 msgstr ""
 
-#: i386.cc:1271 x86_64.cc:1264
+#: i386.cc:1317 x86_64.cc:1264
 #, c-format
 msgid "%s: %s: TLS reloc but no TLS segment\n"
 msgstr ""
 
-#: i386.cc:1306 x86_64.cc:1292
-#, c-format
-msgid "%s: %s: unsupported reloc type %u\n"
-msgstr ""
-
-#: i386.cc:1332
+#: i386.cc:1378
 #, c-format
 msgid "%s: %s: both SUN and GNU model TLS relocations\n"
 msgstr ""
 
-#: i386.cc:1584 x86_64.cc:1463
-#, c-format
-msgid "%s: %s: TLS relocation out of range\n"
-msgstr ""
-
-#: i386.cc:1602 x86_64.cc:1481
-#, c-format
-msgid "%s: %s: TLS relocation against invalid instruction\n"
-msgstr ""
-
 #: merge.cc:247
 #, c-format
 msgid ""
@@ -751,6 +736,16 @@ msgstr ""
 msgid "%s: %s: undefined reference to '%s'\n"
 msgstr ""
 
+#: tls.h:58 x86_64.cc:1463
+#, c-format
+msgid "%s: %s: TLS relocation out of range\n"
+msgstr ""
+
+#: tls.h:77 x86_64.cc:1481
+#, c-format
+msgid "%s: %s: TLS relocation against invalid instruction\n"
+msgstr ""
+
 #. This output is intended to follow the GNU standards.
 #: version.cc:50
 #, c-format
@@ -770,3 +765,8 @@ msgstr ""
 #, c-format
 msgid "%s: %s: unsupported REL reloc section\n"
 msgstr ""
+
+#: x86_64.cc:1292
+#, c-format
+msgid "%s: %s: unsupported reloc type %u\n"
+msgstr ""
diff --git a/gold/tls.h b/gold/tls.h
new file mode 100644 (file)
index 0000000..9324701
--- /dev/null
@@ -0,0 +1,89 @@
+// tls.h -- Thread-Local Storage utility routines for gold   -*- C++ -*-
+
+// Copyright 2006, 2007 Free Software Foundation, Inc.
+// Written by Ian Lance Taylor <iant@google.com>.
+
+// This file is part of gold.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+// MA 02110-1301, USA.
+
+#ifndef GOLD_TLS_H
+#define GOLD_TLS_H
+
+#include "elfcpp.h"
+#include "reloc.h"
+
+namespace gold
+{
+
+namespace tls
+{
+
+// This is used for relocations that can be converted to a different,
+// more efficient type of relocation.
+
+enum Tls_optimization
+{
+  TLSOPT_NONE,    // Can not convert this relocation to a more efficient one.
+  TLSOPT_TO_LD,   // Can convert General Dynamic to Local Dynamic.
+  TLSOPT_TO_LE,   // Can convert GD or LD to Local-Exec.
+  TLSOPT_TO_IE,   // Can convert GD or LD or LE to Initial-Exec.
+};
+
+// Check the range for a TLS relocation.  This is inlined for efficiency.
+
+template<int size, bool big_endian>
+inline void
+check_range(const Relocate_info<size, big_endian>* relinfo,
+            size_t relnum,
+            typename elfcpp::Elf_types<size>::Elf_Addr rel_offset,
+            off_t view_size, off_t off)
+{
+  off_t offset = rel_offset + off;
+  if (offset < 0 || offset > view_size)
+    {
+      fprintf(stderr, _("%s: %s: TLS relocation out of range\n"),
+             program_name,
+             relinfo->location(relnum, rel_offset).c_str());
+      gold_exit(false);
+    }
+}
+
+// Check the validity of a TLS relocation.  This is like assert.
+
+template<int size, bool big_endian>
+inline void
+check_tls(const Relocate_info<size, big_endian>* relinfo,
+          size_t relnum,
+          typename elfcpp::Elf_types<size>::Elf_Addr rel_offset,
+          bool valid)
+{
+  if (!valid)
+    {
+      fprintf(stderr,
+             _("%s: %s: TLS relocation against invalid instruction\n"),
+             program_name,
+             relinfo->location(relnum, rel_offset).c_str());
+      gold_exit(false);
+    }
+}
+
+
+} // End namespace tls.
+
+} // End namespace gold.
+
+#endif // !defined(GOLD_TLS_H)