aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2007-10-08 05:12:59 +0000
committerIan Lance Taylor <iant@google.com>2007-10-08 05:12:59 +0000
commitaf6359d59d84cdd70fd1f400b91bc2fdcbed7dfa (patch)
tree84e183491351cc97eaa1bf73aa71dcfd9be52b8d
parente40747242edfd7ca805f52d14ac80d589065d865 (diff)
downloadbinutils-af6359d59d84cdd70fd1f400b91bc2fdcbed7dfa.zip
binutils-af6359d59d84cdd70fd1f400b91bc2fdcbed7dfa.tar.gz
binutils-af6359d59d84cdd70fd1f400b91bc2fdcbed7dfa.tar.bz2
From Craig Silverstein: add tls.h, use it in i386.cc.
-rw-r--r--gold/Makefile.am1
-rw-r--r--gold/Makefile.in1
-rw-r--r--gold/i386.cc259
-rw-r--r--gold/po/POTFILES.in1
-rw-r--r--gold/po/gold.pot58
-rw-r--r--gold/tls.h89
6 files changed, 253 insertions, 156 deletions
diff --git a/gold/Makefile.am b/gold/Makefile.am
index 87bde55..e9508de 100644
--- a/gold/Makefile.am
+++ b/gold/Makefile.am
@@ -75,6 +75,7 @@ HFILES = \
target.h \
target-reloc.h \
target-select.h \
+ tls.h \
workqueue.h
YFILES = \
diff --git a/gold/Makefile.in b/gold/Makefile.in
index 13a3536..9d9ff8c 100644
--- a/gold/Makefile.in
+++ b/gold/Makefile.in
@@ -326,6 +326,7 @@ HFILES = \
target.h \
target-reloc.h \
target-select.h \
+ tls.h \
workqueue.h
YFILES = \
diff --git a/gold/i386.cc b/gold/i386.cc
index 033a9b9..ce4d961 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -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
diff --git a/gold/po/POTFILES.in b/gold/po/POTFILES.in
index 9628afa..a65d3a5 100644
--- a/gold/po/POTFILES.in
+++ b/gold/po/POTFILES.in
@@ -46,6 +46,7 @@ target.h
target-reloc.h
target-select.cc
target-select.h
+tls.h
version.cc
workqueue.cc
workqueue.h
diff --git a/gold/po/gold.pot b/gold/po/gold.pot
index cf5aea9..20bada8 100644
--- a/gold/po/gold.pot
+++ b/gold/po/gold.pot
@@ -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
index 0000000..9324701c
--- /dev/null
+++ b/gold/tls.h
@@ -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)