* x86_64.cc (Target_x86_64::Scan): Change from struct to class.
authorIan Lance Taylor <ian@airs.com>
Tue, 8 Apr 2008 04:09:59 +0000 (04:09 +0000)
committerIan Lance Taylor <ian@airs.com>
Tue, 8 Apr 2008 04:09:59 +0000 (04:09 +0000)
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.

gold/ChangeLog
gold/x86_64.cc

index 6df30ff8db6f8243c10c735ece1316b83f378c2f..244692fbdccce62644487aea1676e2ed3347c2d8 100644 (file)
@@ -1,5 +1,11 @@
 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.
+
        * output.cc (Output_reloc<SHT_REL>::local_section_offset): Add
        addend parameter.  Change caller.  Handle merge sections.
        (Output_reloc<SHT_REL>::symbol_value): Change parameter type from
index 973787fe7d14c96d47af02368ef0aa2d4c5cc038..f384417694bdf4dff8cebd5afe3415f72f6c57d7 100644 (file)
@@ -150,8 +150,13 @@ class Target_x86_64 : public Sized_target<64, false>
 
  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_target<64, false>
           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_local(Sized_relobj<64, false>* object,
             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_options&,
       // 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_options&,
                       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 General_options& options,
               }
             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 General_options& options,
               }
             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(),