* x86_64.cc (Target_x86_64::saw_tls_block_reloc_): Remove member.
[binutils-gdb.git] / gold / arm.cc
index 85f95429a4b7f1bfa22abcab7af284f145722706..79a96633d4868bd589caa4b4841942738eff4bdf 100644 (file)
@@ -1064,6 +1064,11 @@ class Arm_exidx_cantunwind : public Output_section_data
       this->do_fixed_endian_write<false>(of);
   }
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** ARM cantunwind")); }
+
  private:
   // Implement do_write for a given endianness.
   template<bool big_endian>
@@ -1636,7 +1641,7 @@ class Arm_relobj : public Sized_relobj<32, big_endian>
 
   void
   do_relocate_sections(const Symbol_table* symtab, const Layout* layout,
-                      const unsigned char* pshdrs,
+                      const unsigned char* pshdrs, Output_file* of,
                       typename Sized_relobj<32, big_endian>::Views* pivews);
 
   // Read the symbol information.
@@ -6351,11 +6356,12 @@ Arm_relobj<big_endian>::do_relocate_sections(
     const Symbol_table* symtab,
     const Layout* layout,
     const unsigned char* pshdrs,
+    Output_file* of,
     typename Sized_relobj<32, big_endian>::Views* pviews)
 {
   // Call parent to relocate sections.
   Sized_relobj<32, big_endian>::do_relocate_sections(symtab, layout, pshdrs,
-                                                    pviews); 
+                                                    of, pviews); 
 
   // We do not generate stubs if doing a relocatable link.
   if (parameters->options().relocatable())
@@ -10944,6 +10950,8 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs(
 
       Symbol_value<32> symval;
       const Symbol_value<32> *psymval;
+      bool is_defined_in_discarded_section;
+      unsigned int shndx;
       if (r_sym < local_count)
        {
          sym = NULL;
@@ -10955,45 +10963,53 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs(
           // counterpart in the kept section.  The symbol must not 
           // correspond to a section we are folding.
          bool is_ordinary;
-         unsigned int shndx = psymval->input_shndx(&is_ordinary);
-         if (is_ordinary
-             && shndx != elfcpp::SHN_UNDEF
-             && !arm_object->is_section_included(shndx) 
-              && !(relinfo->symtab->is_section_folded(arm_object, shndx)))
+         shndx = psymval->input_shndx(&is_ordinary);
+         is_defined_in_discarded_section =
+           (is_ordinary
+            && shndx != elfcpp::SHN_UNDEF
+            && !arm_object->is_section_included(shndx)
+            && !relinfo->symtab->is_section_folded(arm_object, shndx));
+
+         // We need to compute the would-be final value of this local
+         // symbol.
+         if (!is_defined_in_discarded_section)
            {
-             if (comdat_behavior == CB_UNDETERMINED)
-               {
-                 std::string name =
-                   arm_object->section_name(relinfo->data_shndx);
-                 comdat_behavior = get_comdat_behavior(name.c_str());
-               }
-             if (comdat_behavior == CB_PRETEND)
-               {
-                  bool found;
-                 typename elfcpp::Elf_types<32>::Elf_Addr value =
-                   arm_object->map_to_kept_section(shndx, &found);
-                 if (found)
-                   symval.set_output_value(value + psymval->input_value());
-                  else
-                    symval.set_output_value(0);
-               }
+             typedef Sized_relobj<32, big_endian> ObjType;
+             typename ObjType::Compute_final_local_value_status status =
+               arm_object->compute_final_local_value(r_sym, psymval, &symval,
+                                                     relinfo->symtab); 
+             if (status == ObjType::CFLV_OK)
+               {
+                 // Currently we cannot handle a branch to a target in
+                 // a merged section.  If this is the case, issue an error
+                 // and also free the merge symbol value.
+                 if (!symval.has_output_value())
+                   {
+                     const std::string& section_name =
+                       arm_object->section_name(shndx);
+                     arm_object->error(_("cannot handle branch to local %u "
+                                         "in a merged section %s"),
+                                       r_sym, section_name.c_str());
+                   }
+                 psymval = &symval;
+               }
              else
-               {
-                  symval.set_output_value(0);
-               }
-             symval.set_no_output_symtab_entry();
-             psymval = &symval;
+               {
+                 // We cannot determine the final value.
+                 continue;  
+               }
            }
        }
       else
        {
-         const Symbol* gsym = arm_object->global_symbol(r_sym);
+         const Symbol* gsym;
+         gsym = arm_object->global_symbol(r_sym);
          gold_assert(gsym != NULL);
          if (gsym->is_forwarder())
            gsym = relinfo->symtab->resolve_forwards(gsym);
 
          sym = static_cast<const Sized_symbol<32>*>(gsym);
-         if (sym->has_symtab_index())
+         if (sym->has_symtab_index() && sym->symtab_index() != -1U)
            symval.set_output_symtab_index(sym->symtab_index());
          else
            symval.set_no_output_symtab_entry();
@@ -11010,9 +11026,53 @@ Target_arm<big_endian>::scan_reloc_section_for_stubs(
          // Skip this if the symbol has not output section.
          if (status == Symbol_table::CFVS_NO_OUTPUT_SECTION)
            continue;
-
          symval.set_output_value(value);
+
+         if (gsym->type() == elfcpp::STT_TLS)
+           symval.set_is_tls_symbol();
+         else if (gsym->type() == elfcpp::STT_GNU_IFUNC)
+           symval.set_is_ifunc_symbol();
          psymval = &symval;
+
+         is_defined_in_discarded_section =
+           (gsym->is_defined_in_discarded_section()
+            && gsym->is_undefined());
+         shndx = 0;
+       }
+
+      Symbol_value<32> symval2;
+      if (is_defined_in_discarded_section)
+       {
+         if (comdat_behavior == CB_UNDETERMINED)
+           {
+             std::string name = arm_object->section_name(relinfo->data_shndx);
+             comdat_behavior = get_comdat_behavior(name.c_str());
+           }
+         if (comdat_behavior == CB_PRETEND)
+           {
+             // FIXME: This case does not work for global symbols.
+             // We have no place to store the original section index.
+             // Fortunately this does not matter for comdat sections,
+             // only for sections explicitly discarded by a linker
+             // script.
+             bool found;
+             typename elfcpp::Elf_types<32>::Elf_Addr value =
+               arm_object->map_to_kept_section(shndx, &found);
+             if (found)
+               symval2.set_output_value(value + psymval->input_value());
+             else
+               symval2.set_output_value(0);
+           }
+         else
+           {
+             if (comdat_behavior == CB_WARNING)
+               gold_warning_at_location(relinfo, i, offset,
+                                        _("relocation refers to discarded "
+                                          "section"));
+             symval2.set_output_value(0);
+           }
+         symval2.set_no_output_symtab_entry();
+         psymval = &symval2;
        }
 
       // If symbol is a section symbol, we don't know the actual type of