[GOLD] R_PPC64_ENTRY support
authorAlan Modra <amodra@gmail.com>
Mon, 7 Dec 2015 02:45:24 +0000 (13:15 +1030)
committerAlan Modra <amodra@gmail.com>
Mon, 7 Dec 2015 02:47:00 +0000 (13:17 +1030)
elfcpp/
* powerpc.h (R_PPC64_ENTRY): Define.
gold/
* powerpc.cc (add_2_2_12, ld_2_12, lis_2): Define.
(Target_powerpc::Scan::local, global): Handle R_PPC64_ENTRY.
(Target_powerpc::Relocate::relocate): Edit code at R_PPC64_ENTRY.

elfcpp/ChangeLog
elfcpp/powerpc.h
gold/ChangeLog
gold/powerpc.cc

index c44333473088050d2c4f1b7cb0c8c6a643cbbb79..0aa8627eb3b4b62ca00ece33dec00b1018e14d98 100644 (file)
@@ -1,3 +1,7 @@
+2015-12-07  Alan Modra  <amodra@gmail.com>
+
+       * powerpc.h (R_PPC64_ENTRY): Define.
+
 2015-11-11  Alan Modra  <amodra@gmail.com>
             Peter Bergner <bergner@vnet.ibm.com>
 
index ae30c8affabddcb5bb10acf275dede376e029d49..a8b005ed98cdb71acca97854e05b9986eaf85514 100644 (file)
@@ -178,6 +178,7 @@ enum
   R_PPC_EMB_RELSDA = 116,
   R_PPC64_REL24_NOTOC = 116,
   R_PPC64_ADDR64_LOCAL = 117,
+  R_PPC64_ENTRY = 118,
 
   R_PPC_VLE_REL8 = 216,
   R_PPC_VLE_REL15 = 217,
index 5ead7da4de77ddda5766502d0cdf8739de5f259b..c4bf4a4d24bbb89df4ca97a8ae56cbd3a4e77cb0 100644 (file)
@@ -1,3 +1,9 @@
+2015-12-07  Alan Modra  <amodra@gmail.com>
+
+       * powerpc.cc (add_2_2_12, ld_2_12, lis_2): Define.
+       (Target_powerpc::Scan::local, global): Handle R_PPC64_ENTRY.
+       (Target_powerpc::Relocate::relocate): Edit code at R_PPC64_ENTRY.
+
 2015-12-03  Vladimir Radosavljevic <Vladimir.Radosavljevic@imgtec.com>
 
        * object.cc (Sized_relobj::do_for_all_local_got_entries): Use
index 39a0324e79c75bd393acd007db48efb704f34645..12215ffe2735b4bd687b3e2980efefb3766cde8e 100644 (file)
@@ -3224,6 +3224,7 @@ Output_data_plt_powerpc<size, big_endian>::add_local_ifunc_entry(
 
 static const uint32_t add_0_11_11      = 0x7c0b5a14;
 static const uint32_t add_2_2_11       = 0x7c425a14;
+static const uint32_t add_2_2_12       = 0x7c426214;
 static const uint32_t add_3_3_2                = 0x7c631214;
 static const uint32_t add_3_3_13       = 0x7c636a14;
 static const uint32_t add_11_0_11      = 0x7d605a14;
@@ -3258,6 +3259,7 @@ static const uint32_t ld_0_12             = 0xe80c0000;
 static const uint32_t ld_2_1           = 0xe8410000;
 static const uint32_t ld_2_2           = 0xe8420000;
 static const uint32_t ld_2_11          = 0xe84b0000;
+static const uint32_t ld_2_12          = 0xe84c0000;
 static const uint32_t ld_11_2          = 0xe9620000;
 static const uint32_t ld_11_11         = 0xe96b0000;
 static const uint32_t ld_12_2          = 0xe9820000;
@@ -3267,6 +3269,7 @@ static const uint32_t lfd_0_1             = 0xc8010000;
 static const uint32_t li_0_0           = 0x38000000;
 static const uint32_t li_12_0          = 0x39800000;
 static const uint32_t lis_0            = 0x3c000000;
+static const uint32_t lis_2            = 0x3c400000;
 static const uint32_t lis_11           = 0x3d600000;
 static const uint32_t lis_12           = 0x3d800000;
 static const uint32_t lvx_0_12_0       = 0x7c0c00ce;
@@ -5607,6 +5610,7 @@ Target_powerpc<size, big_endian>::Scan::local(
     case elfcpp::R_POWERPC_GNU_VTENTRY:
     case elfcpp::R_PPC64_TOCSAVE:
     case elfcpp::R_POWERPC_TLS:
+    case elfcpp::R_PPC64_ENTRY:
       break;
 
     case elfcpp::R_PPC64_TOC:
@@ -5982,6 +5986,7 @@ Target_powerpc<size, big_endian>::Scan::global(
     case elfcpp::R_POWERPC_GNU_VTENTRY:
     case elfcpp::R_PPC_LOCAL24PC:
     case elfcpp::R_POWERPC_TLS:
+    case elfcpp::R_PPC64_ENTRY:
       break;
 
     case elfcpp::R_PPC64_TOC:
@@ -7655,6 +7660,48 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
                }
            }
          break;
+
+       case elfcpp::R_PPC64_ENTRY:
+         value = (target->got_section()->output_section()->address()
+                  + object->toc_base_offset());
+         if (value + 0x80008000 <= 0xffffffff
+             && !parameters->options().output_is_position_independent())
+           {
+             Insn* iview = reinterpret_cast<Insn*>(view);
+             Insn insn1 = elfcpp::Swap<32, big_endian>::readval(iview);
+             Insn insn2 = elfcpp::Swap<32, big_endian>::readval(iview + 1);
+
+             if ((insn1 & ~0xfffc) == ld_2_12
+                 && insn2 == add_2_2_12)
+               {
+                 insn1 = lis_2 + ha(value);
+                 elfcpp::Swap<32, big_endian>::writeval(iview, insn1);
+                 insn2 = addi_2_2 + l(value);
+                 elfcpp::Swap<32, big_endian>::writeval(iview + 1, insn2);
+                 return true;
+               }
+           }
+         else
+           {
+             value -= address;
+             if (value + 0x80008000 <= 0xffffffff)
+               {
+                 Insn* iview = reinterpret_cast<Insn*>(view);
+                 Insn insn1 = elfcpp::Swap<32, big_endian>::readval(iview);
+                 Insn insn2 = elfcpp::Swap<32, big_endian>::readval(iview + 1);
+
+                 if ((insn1 & ~0xfffc) == ld_2_12
+                     && insn2 == add_2_2_12)
+                   {
+                     insn1 = addis_2_12 + ha(value);
+                     elfcpp::Swap<32, big_endian>::writeval(iview, insn1);
+                     insn2 = addi_2_2 + l(value);
+                     elfcpp::Swap<32, big_endian>::writeval(iview + 1, insn2);
+                     return true;
+                   }
+               }
+           }
+         break;
        }
     }