This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch][gold] Fix R_ARM_TLS_LE32 when there is no TLS segment


> I'm having trouble understanding this patch. ÂIf you have SHF_TLS
> sections but you don't have a PT_TLS segment, then as far as I can see
> your program isn't going to work. ÂWhile I can certainly see the
> advantage of producing a better error message, I don't see why the
> linker should be concerned about just which value it generates. ÂThe
> program will fail at runtime anyhow.

A regular program will. This is a reduction from an issue in native
client. In native client we use the linker script to provided three
symbols:
 __tls_template_start, __tls_template_tdata_end and
__tls_template_end. With these symbols the runtime can do the job that
is normally done by ld.so.

I am not sure I understand the reasoning for doing it this way, but
apparently it is because the ELF header doesn't pass the validator and
therefore is not loaded. It should be possible to get the loader to
find the PT_TLS segment and pass that information down, but that would
complicate a part of the trusted code. For more information see

 https://groups.google.com/group/native-client-discuss/browse_thread/thread/9e61d91a5849bf22/f22f2a9a14410431

> That said, a few mechanical comments on the last version of the patch:
>
>
>> @@ -8679,6 +8679,23 @@ Target_arm<big_endian>::Relocate::relocate(
>> Â Âreturn true;
>> Â}
>>
>> +template<bool big_endian>
>> +Output_section *
>> +relocated_section(const Relocate_info<32, big_endian>* relinfo,
>> + Â Â Â Â Â Â Â Â Âconst elfcpp::Rel<32, big_endian>& rel,
>> + Â Â Â Â Â Â Â Â Âconst Sized_symbol<32>* gsym)
>
> This is going to make a global function relocated_section, not a good
> idea. ÂIt should be a static member of Target_arm.

I made it static, is that OK?

I did all other changes as requested.

>
> Ian
>


Thanks,
-- 
Rafael Ãvila de EspÃndola
diff --git a/gold/arm.cc b/gold/arm.cc
index 88102dc..165ac42 100644
--- a/gold/arm.cc
+++ b/gold/arm.cc
@@ -6895,13 +6895,13 @@ Arm_output_data_got<big_endian>::do_write(Output_file* of)
     convert_to_section_size_type(this->data_size());
   unsigned char* const oview = of->get_output_view(offset, oview_size);
 
-  Output_segment* tls_segment = this->layout_->tls_segment();
-  gold_assert(tls_segment != NULL);
+  Output_section* tls_section = this->layout_->tls_section();
+  gold_assert(tls_section != NULL);
   
   // The thread pointer $tp points to the TCB, which is followed by the
   // TLS.  So we need to adjust $tp relative addressing by this amount.
   Arm_address aligned_tcb_size =
-    align_address(ARM_TCB_SIZE, tls_segment->maximum_alignment());
+    align_address(ARM_TCB_SIZE, tls_section->addralign());
 
   for (size_t i = 0; i < this->static_relocs_.size(); ++i)
     {
@@ -8774,6 +8774,23 @@ Target_arm<big_endian>::Relocate::relocate(
   return true;
 }
 
+template<bool big_endian>
+static Output_section *
+relocated_section(const Relocate_info<32, big_endian>* relinfo,
+                  const elfcpp::Rel<32, big_endian>& rel,
+                  const Sized_symbol<32>* gsym)
+{
+  if (gsym)
+    return gsym->output_section();
+  unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
+  const Symbol_value<32>* sym_val =
+      relinfo->object->local_symbol(r_sym);
+  bool is_ordinary;
+  unsigned int input_shndx = sym_val->input_shndx(&is_ordinary);
+  gold_assert(is_ordinary);
+  return relinfo->object->output_section(input_shndx);
+}
+
 // Perform a TLS relocation.
 
 template<bool big_endian>
@@ -8792,7 +8809,6 @@ Target_arm<big_endian>::Relocate::relocate_tls(
 {
   typedef Arm_relocate_functions<big_endian> ArmRelocFuncs;
   typedef Relocate_functions<32, big_endian> RelocFuncs;
-  Output_segment* tls_segment = relinfo->layout->tls_segment();
 
   const Sized_relobj<32, big_endian>* object = relinfo->object;
 
@@ -8892,14 +8908,16 @@ Target_arm<big_endian>::Relocate::relocate_tls(
       // have been created for this location, so do not apply it now.
       if (!parameters->options().shared())
         {
-          gold_assert(tls_segment != NULL);
-
+          Output_section* tls_section = relinfo->layout->tls_section();
 	  // $tp points to the TCB, which is followed by the TLS, so we
 	  // need to add TCB size to the offset.
 	  Arm_address aligned_tcb_size =
-	    align_address(ARM_TCB_SIZE, tls_segment->maximum_alignment());
-          RelocFuncs::rel32(view, value + aligned_tcb_size);
+	    align_address(ARM_TCB_SIZE, tls_section->addralign());
 
+	  Output_section *relocated_sec = relocated_section(relinfo, rel, gsym);
+	  Arm_address section_offset = relocated_sec->address() -
+              tls_section->address();
+	  RelocFuncs::rel32(view, section_offset + value + aligned_tcb_size);
         }
       return ArmRelocFuncs::STATUS_OKAY;
     
diff --git a/gold/layout.cc b/gold/layout.cc
index 36cfa8b..e867d50 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -174,6 +174,7 @@ Layout::Layout(int number_of_input_files, Script_options* script_options)
     special_output_list_(),
     section_headers_(NULL),
     tls_segment_(NULL),
+    tls_section_(NULL),
     relro_segment_(NULL),
     increase_relro_(0),
     symtab_section_(NULL),
@@ -1524,6 +1525,32 @@ Layout::prepare_for_relaxation()
   this->record_output_section_data_from_script_ = true;
 }
 
+// Find the tls section with the lowest address.
+
+Output_section*
+Layout::compute_tls_section() const
+{
+  // Check that this method is used only once.
+  gold_assert(this->tls_section_ == NULL);
+
+  uint64_t align = 0;
+  const Layout::Section_list& list(this->section_list());
+  for (Section_list::const_iterator i = list.begin(); i != list.end(); ++i)
+  {
+    Output_section* sec = *i;
+    if ((sec->flags() & elfcpp::SHF_TLS) == 0)
+      continue;
+    if (sec->addralign() > align)
+      align = sec->addralign();
+    if (this->tls_section_ == NULL
+        || sec->address() < this->tls_section_->address())
+      this->tls_section_ = sec;
+  }
+  gold_assert(this->tls_section_);
+  gold_assert(this->tls_section_->addralign() == align);
+  return this->tls_section_;
+}
+
 // Relaxation loop body:  If target has no relaxation, this runs only once
 // Otherwise, the target relaxation hook is called at the end of
 // each iteration.  If the hook returns true, it means re-layout of
diff --git a/gold/layout.h b/gold/layout.h
index 912be31..6cde964 100644
--- a/gold/layout.h
+++ b/gold/layout.h
@@ -483,6 +483,16 @@ class Layout
   tls_segment() const
   { return this->tls_segment_; }
 
+  // Return the last TLS section. Asserts that there is one and that it
+  // is correctly aligned.
+  Output_section*
+  tls_section() const
+  {
+    if (this->tls_section_)
+      return this->tls_section_;
+    return this->compute_tls_section();
+  }
+
   // Return the normal symbol table.
   Output_section*
   symtab_section() const
@@ -867,6 +877,11 @@ class Layout
   void
   prepare_for_relaxation();
 
+  // Find the last TLS section. Asserts that there is one and that it
+  // is correctly aligned.
+  Output_section*
+  compute_tls_section() const;
+
   // Main body of the relaxation loop, which lays out the section.
   off_t
   relaxation_loop_body(int, Target*, Symbol_table*, Output_segment**,
@@ -968,6 +983,8 @@ class Layout
   Output_section_headers* section_headers_;
   // A pointer to the PT_TLS segment if there is one.
   Output_segment* tls_segment_;
+  // A cache pointer to the last SHF_TLS segction.
+  mutable Output_section* tls_section_;
   // A pointer to the PT_GNU_RELRO segment if there is one.
   Output_segment* relro_segment_;
   // A backend may increase the size of the PT_GNU_RELRO segment if

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]