gdb/testsuite/
[binutils-gdb.git] / gold / i386.cc
index f2a7b53f7ad441b91038fd3b26a23311d0f3a0d1..1776383249f58ba2f90f371a74e3b26aa8d7b54c 100644 (file)
@@ -64,6 +64,10 @@ class Target_i386 : public Target_freebsd<32, false>
       got_mod_index_offset_(-1U), tls_base_symbol_defined_(false)
   { }
 
+  inline bool
+  can_check_for_function_pointers() const
+  { return true; }
+
   // Process the relocations to determine unreferenced sections for 
   // garbage collection.
   void
@@ -167,6 +171,10 @@ class Target_i386 : public Target_freebsd<32, false>
     return Target::do_is_local_label_name(name);
   }
 
+  // Return whether SYM is call to a non-split function.
+  bool
+  do_is_call_to_non_split(const Symbol* sym, unsigned int) const;
+
   // Adjust -fstack-split code which calls non-stack-split code.
   void
   do_calls_non_split(Relobj* object, unsigned int shndx,
@@ -202,6 +210,29 @@ class Target_i386 : public Target_freebsd<32, false>
           const elfcpp::Rel<32, false>& reloc, unsigned int r_type,
           Symbol* gsym);
 
+    inline bool
+    local_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout,
+                                       Target_i386* target,
+                                       Sized_relobj<32, false>* object,
+                                       unsigned int data_shndx,
+                                       Output_section* output_section,
+                                       const elfcpp::Rel<32, false>& reloc,
+                                       unsigned int r_type,
+                                       const elfcpp::Sym<32, false>& lsym);
+
+    inline bool
+    global_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout,
+                                        Target_i386* target,
+                                        Sized_relobj<32, false>* object,
+                                        unsigned int data_shndx,
+                                        Output_section* output_section,
+                                        const elfcpp::Rel<32, false>& reloc,
+                                        unsigned int r_type,
+                                        Symbol* gsym);
+
+    inline bool
+    possible_function_pointer_reloc(unsigned int r_type);
+
     static void
     unsupported_reloc_local(Sized_relobj<32, false>*, unsigned int r_type);
 
@@ -1214,6 +1245,55 @@ Target_i386::Scan::unsupported_reloc_global(Sized_relobj<32, false>* object,
             object->name().c_str(), r_type, gsym->demangled_name().c_str());
 }
 
+inline bool
+Target_i386::Scan::possible_function_pointer_reloc(unsigned int r_type)
+{
+  switch (r_type)
+    {
+    case elfcpp::R_386_32:
+    case elfcpp::R_386_16:
+    case elfcpp::R_386_8:
+    case elfcpp::R_386_GOTOFF:
+    case elfcpp::R_386_GOT32:
+      {
+        return true;
+      }
+    default:
+      return false;
+    }
+  return false;
+}
+
+inline bool
+Target_i386::Scan::local_reloc_may_be_function_pointer(
+  Symbol_table* ,
+  Layout* ,
+  Target_i386* ,
+  Sized_relobj<32, false>* ,
+  unsigned int ,
+  Output_section* ,
+  const elfcpp::Rel<32, false>& ,
+  unsigned int r_type,
+  const elfcpp::Sym<32, false>&)
+{
+  return possible_function_pointer_reloc(r_type);
+}
+
+inline bool
+Target_i386::Scan::global_reloc_may_be_function_pointer(
+  Symbol_table* ,
+  Layout* ,
+  Target_i386* ,
+  Sized_relobj<32, false>* ,
+  unsigned int ,
+  Output_section* ,
+  const elfcpp::Rel<32, false>& ,
+  unsigned int r_type,
+  Symbol*)
+{
+  return possible_function_pointer_reloc(r_type);
+}
+
 // Scan a relocation for a global symbol.
 
 inline void
@@ -1897,10 +1977,9 @@ Target_i386::Relocate::relocate_tls(const Relocate_info<32, false>* relinfo,
 
   elfcpp::Elf_types<32>::Elf_Addr value = psymval->value(object, 0);
 
-  const bool is_final =
-    (gsym == NULL
-     ? !parameters->options().output_is_position_independent()
-     : gsym->final_value_is_known());
+  const bool is_final = (gsym == NULL
+                        ? !parameters->options().shared()
+                        : gsym->final_value_is_known());
   const tls::Tls_optimization optimized_type
       = Target_i386::optimize_tls_reloc(is_final, r_type);
   switch (r_type)
@@ -2701,6 +2780,17 @@ Target_i386::do_code_fill(section_size_type length) const
   return std::string(nops[length], length);
 }
 
+// Return whether SYM should be treated as a call to a non-split
+// function.  We don't want that to be true of a call to a
+// get_pc_thunk function.
+
+bool
+Target_i386::do_is_call_to_non_split(const Symbol* sym, unsigned int) const
+{
+  return (sym->type() == elfcpp::STT_FUNC
+         && !is_prefix_of("__i686.get_pc_thunk.", sym->name()));
+}
+
 // FNOFFSET in section SHNDX in OBJECT is the start of a function
 // compiled with -fstack-split.  The function calls non-stack-split
 // code.  We have to change the function so that it always ensures