gdb/testsuite/
[binutils-gdb.git] / gold / i386.cc
index eb4ef0abc78df7a63c517f87980747d4e5b95f97..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,
@@ -203,24 +211,27 @@ class Target_i386 : public Target_freebsd<32, false>
           Symbol* gsym);
 
     inline bool
-    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 ,
-                                       const elfcpp::Sym<32, false>&)
-    { return false; }
+    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
-    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 , Symbol*)
-    { return false; }
+    possible_function_pointer_reloc(unsigned int r_type);
 
     static void
     unsupported_reloc_local(Sized_relobj<32, false>*, unsigned int r_type);
@@ -1234,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
@@ -2720,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