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]

PATCH COMMITTED: gold check for unsupported x86-64 dynamic relocs


The x86-64 dynamic linker in glibc does not support the full set of
x86-64 dynamic relocs.  The GNU linker issues an error if it is going
to emit an unsupported dynamic reloc.  I committed this patch to make
gold do the same.

Ian


2008-04-07  Ian Lance Taylor  <iant@google.com>

	* x86_64.cc (Target_x86_64::Scan): Change from struct to class.
	Add issued_non_pic_error_ field.  Declare check_non_pic.
	(Target_x86_64::Scan::check_non_pic): New function.
	(Target_x86_64::Scan::local): Call check_non_pic as appropriate.
	(Target_x86_64::Scan::global): Likewise.


Index: x86_64.cc
===================================================================
RCS file: /cvs/src/src/gold/x86_64.cc,v
retrieving revision 1.58
diff -u -u -p -r1.58 x86_64.cc
--- x86_64.cc	26 Mar 2008 23:36:46 -0000	1.58
+++ x86_64.cc	8 Apr 2008 04:06:22 -0000
@@ -150,8 +150,13 @@ class Target_x86_64 : public Sized_targe
 
  private:
   // The class which scans relocations.
-  struct Scan
+  class Scan
   {
+  public:
+    Scan()
+      : issued_non_pic_error_(false)
+    { }
+
     inline void
     local(const General_options& options, Symbol_table* symtab,
 	  Layout* layout, Target_x86_64* target,
@@ -170,12 +175,19 @@ class Target_x86_64 : public Sized_targe
 	   const elfcpp::Rela<64, false>& reloc, unsigned int r_type,
 	   Symbol* gsym);
 
+  private:
     static void
     unsupported_reloc_local(Sized_relobj<64, false>*, unsigned int r_type);
 
     static void
     unsupported_reloc_global(Sized_relobj<64, false>*, unsigned int r_type,
 			     Symbol*);
+
+    void
+    check_non_pic(Relobj*, unsigned int r_type);
+
+    // Whether we have issued an error about a non-PIC compilation.
+    bool issued_non_pic_error_;
   };
 
   // The class which implements relocation.
@@ -802,6 +814,48 @@ Target_x86_64::Scan::unsupported_reloc_l
 	     object->name().c_str(), r_type);
 }
 
+// We are about to emit a dynamic relocation of type R_TYPE.  If the
+// dynamic linker does not support it, issue an error.  The GNU linker
+// only issues a non-PIC error for an allocated read-only section.
+// Here we know the section is allocated, but we don't know that it is
+// read-only.  But we check for all the relocation types which the
+// glibc dynamic linker supports, so it seems appropriate to issue an
+// error even if the section is not read-only.
+
+void
+Target_x86_64::Scan::check_non_pic(Relobj* object, unsigned int r_type)
+{
+  switch (r_type)
+    {
+      // These are the relocation types supported by glibc for x86_64.
+    case elfcpp::R_X86_64_RELATIVE:
+    case elfcpp::R_X86_64_GLOB_DAT:
+    case elfcpp::R_X86_64_JUMP_SLOT:
+    case elfcpp::R_X86_64_DTPMOD64:
+    case elfcpp::R_X86_64_DTPOFF64:
+    case elfcpp::R_X86_64_TPOFF64:
+    case elfcpp::R_X86_64_64:
+    case elfcpp::R_X86_64_32:
+    case elfcpp::R_X86_64_PC32:
+    case elfcpp::R_X86_64_COPY:
+      return;
+
+    default:
+      // This prevents us from issuing more than one error per reloc
+      // section.  But we can still wind up issuing more than one
+      // error per object file.
+      if (this->issued_non_pic_error_)
+        return;
+      object->error(_("requires unsupported dynamic reloc; "
+                      "recompile with -fPIC"));
+      this->issued_non_pic_error_ = true;
+      return;
+
+    case elfcpp::R_X86_64_NONE:
+      gold_unreachable();
+    }
+}
+
 // Scan a relocation for a local symbol.
 
 inline void
@@ -852,6 +906,8 @@ Target_x86_64::Scan::local(const General
       // because that is always a 64-bit relocation.
       if (parameters->options().output_is_position_independent())
         {
+          this->check_non_pic(object, r_type);
+
           Reloc_section* rela_dyn = target->rela_dyn_section(layout);
           if (lsym.get_st_type() != elfcpp::STT_SECTION)
             {
@@ -915,6 +971,8 @@ Target_x86_64::Scan::local(const General
                       object->local_got_offset(r_sym, GOT_TYPE_STANDARD), 0);
                 else
                   {
+                    this->check_non_pic(object, r_type);
+
                     gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
                     rela_dyn->add_local(
                         object, r_sym, r_type, got,
@@ -1100,6 +1158,7 @@ Target_x86_64::Scan::global(const Genera
               }
             else
               {
+                this->check_non_pic(object, r_type);
                 Reloc_section* rela_dyn = target->rela_dyn_section(layout);
                 rela_dyn->add_global(gsym, r_type, output_section, object,
                                      data_shndx, reloc.get_r_offset(),
@@ -1130,6 +1189,7 @@ Target_x86_64::Scan::global(const Genera
               }
             else
               {
+                this->check_non_pic(object, r_type);
                 Reloc_section* rela_dyn = target->rela_dyn_section(layout);
                 rela_dyn->add_global(gsym, r_type, output_section, object,
                                      data_shndx, reloc.get_r_offset(),

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