Adjust the value of _GLOBAL_OFFSET_TABLE_ for got bigger than 0x8000
authorWalter Lee <walt@tilera.com>
Wed, 3 Oct 2012 00:58:03 +0000 (00:58 +0000)
committerWalter Lee <walt@tilera.com>
Wed, 3 Oct 2012 00:58:03 +0000 (00:58 +0000)
bytes, so that the 16 bit relocations have a greater chance of
working.
* tilegx.cc (Target_tilegx::do_finalize_sections): Adjust
global_offset_table_ value for larget got.
(Target_tilegx::Relocate::relocate): Handle adjusted got value.

gold/ChangeLog
gold/tilegx.cc

index 24795867849c240a638f41782b15c075e1e66f1e..125d4627282448284c36a204dde7eed00a4d8da6 100644 (file)
@@ -1,3 +1,9 @@
+2012-10-02  Jiong Wang  <jiwang@tilera.com>
+
+       * tilegx.cc (Target_tilegx::do_finalize_sections): Adjust
+       global_offset_table_ value for larget got.
+       (Target_tilegx::Relocate::relocate): Handle adjusted got value.
+
 2012-09-29  Alan Modra  <amodra@gmail.com>
 
        * powerpc.cc (Target_powerpc::iplt_): New output section.
index 037bf5458045f6940c7f192237cfadcc0be5ea49..a209a97106ab3921e96f296d6c1cd7d2c837b9df 100644 (file)
@@ -4256,6 +4256,13 @@ Target_tilegx<size, big_endian>::do_finalize_sections(
     {
       uint64_t data_size = this->got_->current_data_size();
       symtab->get_sized_symbol<size>(sym)->set_symsize(data_size);
+
+      // If the .got section is more than 0x8000 bytes, we add
+      // 0x8000 to the value of _GLOBAL_OFFSET_TABLE_, so that 16
+      // bit relocations have a greater chance of working.
+      if (data_size >= 0x8000)
+        symtab->get_sized_symbol<size>(sym)->set_value(
+          symtab->get_sized_symbol<size>(sym)->value() + 0x8000);
     }
 
   if (parameters->doing_static_link()
@@ -4347,7 +4354,10 @@ Target_tilegx<size, big_endian>::Relocate::relocate(
   // Get the GOT offset if needed.
   // For tilegx, the GOT pointer points to the start of the GOT section.
   bool have_got_offset = false;
-  unsigned int got_offset = 0;
+  int got_offset = 0;
+  int got_base = target->got_ != NULL
+                 ? target->got_->current_data_size() >= 0x8000 ? 0x8000 : 0
+                 : 0;
   unsigned int got_type = GOT_TYPE_STANDARD;
   bool always_apply_relocation = false;
   switch (r_type)
@@ -4361,13 +4371,14 @@ Target_tilegx<size, big_endian>::Relocate::relocate(
       if (gsym != NULL)
         {
           gold_assert(gsym->has_got_offset(got_type));
-          got_offset = gsym->got_offset(got_type);
+          got_offset = gsym->got_offset(got_type) - got_base;
         }
       else
         {
           unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
           gold_assert(object->local_has_got_offset(r_sym, got_type));
-          got_offset = object->local_got_offset(r_sym, got_type);
+          got_offset =
+            object->local_got_offset(r_sym, got_type) - got_base;
         }
       have_got_offset = true;
       break;
@@ -4590,12 +4601,13 @@ Target_tilegx<size, big_endian>::Relocate::relocate(
               if (have_got_offset) {
                 if (gsym != NULL) {
                   gold_assert(gsym->has_got_offset(got_type));
-                  got_offset = gsym->got_offset(got_type);
+                  got_offset = gsym->got_offset(got_type) - got_base;
                 } else {
                   unsigned int r_sym
                      = elfcpp::elf_r_sym<size>(rela.get_r_info());
                   gold_assert(object->local_has_got_offset(r_sym, got_type));
-                  got_offset = object->local_got_offset(r_sym, got_type);
+                  got_offset =
+                    object->local_got_offset(r_sym, got_type) - got_base;
                 }
               }