From Craig Silverstein: add tls.h, use it in i386.cc.

This commit is contained in:
Ian Lance Taylor 2007-10-08 05:12:59 +00:00
parent e40747242e
commit af6359d59d
6 changed files with 254 additions and 157 deletions

View File

@ -75,6 +75,7 @@ HFILES = \
target.h \
target-reloc.h \
target-select.h \
tls.h \
workqueue.h
YFILES = \

View File

@ -326,6 +326,7 @@ HFILES = \
target.h \
target-reloc.h \
target-select.h \
tls.h \
workqueue.h
YFILES = \

View 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

View File

@ -46,6 +46,7 @@ target.h
target-reloc.h
target-select.cc
target-select.h
tls.h
version.cc
workqueue.cc
workqueue.h

View 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
#: i386.cc:727 x86_64.cc:766 x86_64.cc:782
#, c-format
msgid "%s: %s: unsupported reloc %u against local symbol\n"
msgstr ""
#: 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: unexpected reloc %u in object file\n"
msgstr ""
#: i386.cc:816 i386.cc:836 x86_64.cc:766 x86_64.cc:782
#, c-format
msgid "%s: %s: unsupported reloc %u against local symbol\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 ""

89
gold/tls.h Normal file
View File

@ -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)