Check R_386_GOT32/R_386_GOT32X without base register
authorH.J. Lu <hjl.tools@gmail.com>
Wed, 28 Oct 2015 16:15:17 +0000 (09:15 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 28 Oct 2015 16:15:40 +0000 (09:15 -0700)
The R_386_GOT32 and R_386_GOT32X relocations may be used without base
register:

movl bar@GOT, %eax

Its calculation is G + A, instead of G + A - GOT, and it can only used
to generate non-PIC executable.  Include the .got.plt section address
for R_386_GOT32 and R_386_GOT32X relocations without base register.
Don't allow R_386_GOT32 and R_386_GOT32X relocations without base
register when making a PIC output.

PR gold/19177
* i386.cc (Target_i386::Relocate::relocate): Check R_386_GOT32
and R_386_GOT32X relocations without base register.

gold/ChangeLog
gold/i386.cc

index dc1c0ea2e2f80ca2611728526e5ba33f0397aaa0..c3cf6860f6cc2df4f79aa0fae69ae4be998bcbe8 100644 (file)
@@ -1,3 +1,9 @@
+2015-10-28  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR gold/19177
+       * i386.cc (Target_i386::Relocate::relocate): Check R_386_GOT32
+       and R_386_GOT32X relocations without base register.
+
 2015-10.27  Han Shen  <shenhan@google.com>
 
        PR gold/19042 - unsupported reloc 311/312.
index 36c57241ef9f4f64654e6561fb7606a37608ba99..4c18de077a5abc1310dbb3ee6c7bc73cabd4acc1 100644 (file)
@@ -2790,6 +2790,8 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
        }
     }
 
+  bool baseless;
+
   switch (r_type)
     {
     case elfcpp::R_386_NONE:
@@ -2839,6 +2841,22 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
 
     case elfcpp::R_386_GOT32:
     case elfcpp::R_386_GOT32X:
+      baseless = (view[-1] & 0xc7) == 0x5;
+      // R_386_GOT32 and R_386_GOT32X don't work without base register
+      // when generating a position-independent output file.
+      if (baseless
+         && parameters->options().output_is_position_independent())
+       {
+         if(gsym)
+           gold_error_at_location(relinfo, relnum, rel.get_r_offset(),
+                                  _("unexpected reloc %u against global symbol %s without base register in object file when generating a position-independent output file"),
+                                  r_type, gsym->demangled_name().c_str());
+         else
+           gold_error_at_location(relinfo, relnum, rel.get_r_offset(),
+                                  _("unexpected reloc %u against local symbol without base register in object file when generating a position-independent output file"),
+                                  r_type);
+       }
+
       // Convert
       // mov foo@GOT(%reg), %reg
       // to
@@ -2852,8 +2870,11 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
        {
          view[-2] = 0x8d;
          elfcpp::Elf_types<32>::Elf_Addr value;
-         value = (psymval->value(object, 0)
-                  - target->got_plt_section()->address());
+         value = psymval->value(object, 0);
+         // Don't subtract the .got.plt section address for baseless
+         // addressing.
+         if (!baseless)
+           value -= target->got_plt_section()->address();
          Relocate_functions<32, false>::rel32(view, value);
        }
       else
@@ -2875,6 +2896,9 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
              got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
                            - target->got_size());
            }
+         // Add the .got.plt section address for baseless addressing.
+         if (baseless)
+           got_offset += target->got_plt_section()->address();
          Relocate_functions<32, false>::rel32(view, got_offset);
        }
       break;