aboutsummaryrefslogtreecommitdiff
path: root/gold/output.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2007-11-14 22:31:02 +0000
committerIan Lance Taylor <iant@google.com>2007-11-14 22:31:02 +0000
commit07f397aba39f619db4fdce42c9e91cb07dd4dc68 (patch)
tree5cc86b1998b729454448c3f3429154dbdebde33d /gold/output.cc
parentc224138d88196fe7cabce4fe554c10a1520f5a4f (diff)
downloadgdb-07f397aba39f619db4fdce42c9e91cb07dd4dc68.zip
gdb-07f397aba39f619db4fdce42c9e91cb07dd4dc68.tar.gz
gdb-07f397aba39f619db4fdce42c9e91cb07dd4dc68.tar.bz2
From Cary Coutant: Improve i386 shared library TLS support.
Diffstat (limited to 'gold/output.cc')
-rw-r--r--gold/output.cc55
1 files changed, 53 insertions, 2 deletions
diff --git a/gold/output.cc b/gold/output.cc
index b191725..ef5c509 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -743,12 +743,59 @@ Output_data_got<size, big_endian>::add_local(
{
if (object->local_has_got_offset(symndx))
return false;
+
this->entries_.push_back(Got_entry(object, symndx));
this->set_got_size();
object->set_local_got_offset(symndx, this->last_got_offset());
return true;
}
+// Add an entry (or a pair of entries) for a global TLS symbol to the GOT.
+// In a pair of entries, the first value in the pair will be used for the
+// module index, and the second value will be used for the dtv-relative
+// offset. This returns true if this is a new GOT entry, false if the symbol
+// already has a GOT entry.
+
+template<int size, bool big_endian>
+bool
+Output_data_got<size, big_endian>::add_global_tls(Symbol* gsym,
+ bool need_pair)
+{
+ if (gsym->has_tls_got_offset(need_pair))
+ return false;
+
+ this->entries_.push_back(Got_entry(gsym));
+ gsym->set_tls_got_offset(this->last_got_offset(), need_pair);
+ if (need_pair)
+ this->entries_.push_back(Got_entry(gsym));
+ this->set_got_size();
+ return true;
+}
+
+// Add an entry (or a pair of entries) for a local TLS symbol to the GOT.
+// In a pair of entries, the first value in the pair will be used for the
+// module index, and the second value will be used for the dtv-relative
+// offset. This returns true if this is a new GOT entry, false if the symbol
+// already has a GOT entry.
+
+template<int size, bool big_endian>
+bool
+Output_data_got<size, big_endian>::add_local_tls(
+ Sized_relobj<size, big_endian>* object,
+ unsigned int symndx,
+ bool need_pair)
+{
+ if (object->local_has_tls_got_offset(symndx, need_pair))
+ return false;
+
+ this->entries_.push_back(Got_entry(object, symndx));
+ object->set_local_tls_got_offset(symndx, this->last_got_offset(), need_pair);
+ if (need_pair)
+ this->entries_.push_back(Got_entry(object, symndx));
+ this->set_got_size();
+ return true;
+}
+
// Write out the GOT.
template<int size, bool big_endian>
@@ -1432,8 +1479,12 @@ Output_segment::add_output_section(Output_section* os,
// SHF_TLS sections. An SHF_TLS/SHT_NOBITS section is a special
// case: we group the SHF_TLS/SHT_NOBITS sections right after the
// SHF_TLS/SHT_PROGBITS sections. This lets us set up PT_TLS
- // correctly.
- if ((os->flags() & elfcpp::SHF_TLS) != 0 && !this->output_data_.empty())
+ // correctly. SHF_TLS sections get added to both a PT_LOAD segment
+ // and the PT_TLS segment -- we do this grouping only for the
+ // PT_LOAD segment.
+ if (this->type_ != elfcpp::PT_TLS
+ && (os->flags() & elfcpp::SHF_TLS) != 0
+ && !this->output_data_.empty())
{
pdl = &this->output_data_;
bool nobits = os->type() == elfcpp::SHT_NOBITS;