From Craig Silverstein: support local GOT relocs for i386.
authorIan Lance Taylor <iant@google.com>
Tue, 16 Oct 2007 00:42:36 +0000 (00:42 +0000)
committerIan Lance Taylor <iant@google.com>
Tue, 16 Oct 2007 00:42:36 +0000 (00:42 +0000)
gold/i386.cc
gold/x86_64.cc

index 81d02b9..d82e50b 100644 (file)
@@ -737,8 +737,8 @@ Target_i386::Scan::local(const General_options&,
                         Layout* layout,
                         Target_i386* target,
                         Sized_relobj<32, false>* object,
-                        unsigned int,
-                        const elfcpp::Rel<32, false>&,
+                        unsigned int data_shndx,
+                        const elfcpp::Rel<32, false>& reloc,
                         unsigned int r_type,
                         const elfcpp::Sym<32, false>&)
 {
@@ -768,6 +768,25 @@ Target_i386::Scan::local(const General_options&,
       target->got_section(symtab, layout);
       break;
 
+    case elfcpp::R_386_GOT32:
+      {
+        // The symbol requires a GOT entry.
+        Output_data_got<32, false>* got = target->got_section(symtab, layout);
+        unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+        if (got->add_local(object, r_sym))
+          {
+            // If we are generating a shared object, we need to add a
+            // dynamic RELATIVE relocation for this symbol.
+            if (parameters->output_is_shared())
+              {
+                Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+                rel_dyn->add_local(object, 0, elfcpp::R_386_RELATIVE,
+                                   data_shndx, reloc.get_r_offset());
+              }
+          }
+      }
+      break;
+
       // These are relocations which should only be seen by the
       // dynamic linker, and should never be seen here.
     case elfcpp::R_386_COPY:
@@ -842,7 +861,6 @@ Target_i386::Scan::local(const General_options&,
       }
       break;
 
-    case elfcpp::R_386_GOT32:
     case elfcpp::R_386_PLT32:
     case elfcpp::R_386_32PLT:
     case elfcpp::R_386_TLS_GD_32:
@@ -1176,6 +1194,29 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
 
   const Sized_relobj<32, false>* object = relinfo->object;
 
+  // Get the GOT offset if needed.
+  bool have_got_offset = false;
+  unsigned int got_offset = 0;
+  switch (r_type)
+    {
+    case elfcpp::R_386_GOT32:
+      if (gsym != NULL)
+        {
+          gold_assert(gsym->has_got_offset());
+          got_offset = gsym->got_offset();
+        }
+      else
+        {
+          unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
+          got_offset = object->local_got_offset(r_sym);
+        }
+      have_got_offset = true;
+      break;
+
+    default:
+      break;
+    }
+
   switch (r_type)
     {
     case elfcpp::R_386_NONE:
@@ -1214,10 +1255,8 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
       break;
 
     case elfcpp::R_386_GOT32:
-      // Local GOT offsets not yet supported.
-      gold_assert(gsym);
-      gold_assert(gsym->has_got_offset());
-      Relocate_functions<32, false>::rel32(view, gsym->got_offset());
+      gold_assert(have_got_offset);
+      Relocate_functions<32, false>::rel32(view, got_offset);
       break;
 
     case elfcpp::R_386_GOTOFF:
index 34a53ac..75c2b7f 100644 (file)
@@ -1181,7 +1181,6 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
     default:
       break;
     }
-  
 
   switch (r_type)
     {