Handle CRLF when reading XML on Windows
[deliverable/binutils-gdb.git] / gold / powerpc.cc
index c8d4414df7184a13f5ed8f339786f4a8eeb1e06f..ad35095ccd585412619ff62b72d05c318c1c639c 100644 (file)
@@ -249,6 +249,12 @@ public:
   make_toc_relative(Target_powerpc<size, big_endian>* target,
                    Address* value);
 
+  bool
+  make_got_relative(Target_powerpc<size, big_endian>* target,
+                   const Symbol_value<size>* psymval,
+                   Address addend,
+                   Address* value);
+
   // Perform the Sized_relobj_file method, then set up opd info from
   // .opd relocs.
   void
@@ -1990,11 +1996,15 @@ private:
     typedef typename elfcpp::Swap<fieldsize, big_endian>::Valtype Valtype;
     Valtype* wv = reinterpret_cast<Valtype*>(view);
     Valtype val = elfcpp::Swap<fieldsize, big_endian>::readval(wv);
-    Valtype reloc = value >> right_shift;
+    if (overflow == CHECK_SIGNED)
+      value = static_cast<SignedAddress>(value) >> right_shift;
+    else
+      value = value >> right_shift;
+    Valtype reloc = value;
     val &= ~dst_mask;
     reloc &= dst_mask;
     elfcpp::Swap<fieldsize, big_endian>::writeval(wv, val | reloc);
-    return overflowed<valsize>(value >> right_shift, overflow);
+    return overflowed<valsize>(value, overflow);
   }
 
   // Do a simple RELA relocation, unaligned.
@@ -2017,11 +2027,15 @@ private:
     typedef typename elfcpp::Swap_unaligned<fieldsize, big_endian>::Valtype
       Valtype;
     Valtype val = elfcpp::Swap<fieldsize, big_endian>::readval(view);
-    Valtype reloc = value >> right_shift;
+    if (overflow == CHECK_SIGNED)
+      value = static_cast<SignedAddress>(value) >> right_shift;
+    else
+      value = value >> right_shift;
+    Valtype reloc = value;
     val &= ~dst_mask;
     reloc &= dst_mask;
     elfcpp::Swap_unaligned<fieldsize, big_endian>::writeval(view, val | reloc);
-    return overflowed<valsize>(value >> right_shift, overflow);
+    return overflowed<valsize>(value, overflow);
   }
 
 public:
@@ -2387,6 +2401,25 @@ Powerpc_relobj<size, big_endian>::make_toc_relative(
   return true;
 }
 
+template<int size, bool big_endian>
+bool
+Powerpc_relobj<size, big_endian>::make_got_relative(
+    Target_powerpc<size, big_endian>* target,
+    const Symbol_value<size>* psymval,
+    Address addend,
+    Address* value)
+{
+  Address addr = psymval->value(this, addend);
+  Address got_base = (target->got_section()->output_section()->address()
+                     + this->toc_base_offset());
+  addr -= got_base;
+  if (addr + 0x80008000 > 0xffffffff)
+    return false;
+
+  *value = addr;
+  return true;
+}
+
 // Perform the Sized_relobj_file method, then set up opd info from
 // .opd relocs.
 
@@ -7172,6 +7205,15 @@ Target_powerpc<size, big_endian>::Scan::get_reference_flags(
     case elfcpp::R_POWERPC_ADDR16_LO:
     case elfcpp::R_POWERPC_ADDR16_HI:
     case elfcpp::R_POWERPC_ADDR16_HA:
+    case elfcpp::R_PPC64_ADDR16_HIGHER34:
+    case elfcpp::R_PPC64_ADDR16_HIGHERA34:
+    case elfcpp::R_PPC64_ADDR16_HIGHEST34:
+    case elfcpp::R_PPC64_ADDR16_HIGHESTA34:
+    case elfcpp::R_PPC64_D34:
+    case elfcpp::R_PPC64_D34_LO:
+    case elfcpp::R_PPC64_D34_HI30:
+    case elfcpp::R_PPC64_D34_HA30:
+    case elfcpp::R_PPC64_D28:
       ref = Symbol::ABSOLUTE_REF;
       break;
 
@@ -7240,6 +7282,14 @@ Target_powerpc<size, big_endian>::Scan::get_reference_flags(
 
     case elfcpp::R_POWERPC_GOT_TPREL16:
     case elfcpp::R_POWERPC_TLS:
+    case elfcpp::R_PPC64_TLSGD:
+    case elfcpp::R_PPC64_TLSLD:
+    case elfcpp::R_PPC64_TPREL34:
+    case elfcpp::R_PPC64_DTPREL34:
+    case elfcpp::R_PPC64_GOT_TLSGD34:
+    case elfcpp::R_PPC64_GOT_TLSLD34:
+    case elfcpp::R_PPC64_GOT_TPREL34:
+    case elfcpp::R_PPC64_GOT_DTPREL34:
       ref = Symbol::TLS_REF;
       break;
 
@@ -7305,7 +7355,6 @@ Target_powerpc<size, big_endian>::Scan::check_non_pic(Relobj* object,
     case elfcpp::R_POWERPC_ADDR14_BRTAKEN:
     case elfcpp::R_POWERPC_ADDR14_BRNTAKEN:
     case elfcpp::R_POWERPC_REL32:
-    case elfcpp::R_POWERPC_REL24:
     case elfcpp::R_POWERPC_TPREL16:
     case elfcpp::R_POWERPC_TPREL16_LO:
     case elfcpp::R_POWERPC_TPREL16_HI:
@@ -7354,6 +7403,7 @@ Target_powerpc<size, big_endian>::Scan::check_non_pic(Relobj* object,
        {
          // These are the relocation types supported only on 32-bit.
          // ??? glibc ld.so doesn't need to support these.
+       case elfcpp::R_POWERPC_REL24:
        case elfcpp::R_POWERPC_DTPREL16:
        case elfcpp::R_POWERPC_DTPREL16_LO:
        case elfcpp::R_POWERPC_DTPREL16_HI:
@@ -7584,8 +7634,6 @@ Target_powerpc<size, big_endian>::Scan::local(
     case elfcpp::R_PPC64_REL16_HIGHERA34:
     case elfcpp::R_PPC64_REL16_HIGHEST34:
     case elfcpp::R_PPC64_REL16_HIGHESTA34:
-      break;
-
     case elfcpp::R_PPC64_D34:
     case elfcpp::R_PPC64_D34_LO:
     case elfcpp::R_PPC64_D34_HI30:
@@ -7593,7 +7641,8 @@ Target_powerpc<size, big_endian>::Scan::local(
     case elfcpp::R_PPC64_D28:
     case elfcpp::R_PPC64_PCREL34:
     case elfcpp::R_PPC64_PCREL28:
-      target->set_powerxx_stubs();
+    case elfcpp::R_PPC64_TPREL34:
+    case elfcpp::R_PPC64_DTPREL34:
       break;
 
     case elfcpp::R_PPC64_TOC:
@@ -7687,8 +7736,6 @@ Target_powerpc<size, big_endian>::Scan::local(
 
     case elfcpp::R_PPC64_PLT_PCREL34:
     case elfcpp::R_PPC64_PLT_PCREL34_NOTOC:
-      target->set_powerxx_stubs();
-      // Fall through.
     case elfcpp::R_POWERPC_PLT16_LO:
     case elfcpp::R_POWERPC_PLT16_HI:
     case elfcpp::R_POWERPC_PLT16_HA:
@@ -7788,8 +7835,6 @@ Target_powerpc<size, big_endian>::Scan::local(
       break;
 
     case elfcpp::R_PPC64_GOT_PCREL34:
-      target->set_powerxx_stubs();
-      // Fall through.
     case elfcpp::R_POWERPC_GOT16:
     case elfcpp::R_POWERPC_GOT16_LO:
     case elfcpp::R_POWERPC_GOT16_HI:
@@ -7838,6 +7883,7 @@ Target_powerpc<size, big_endian>::Scan::local(
       target->got_section(symtab, layout);
       break;
 
+    case elfcpp::R_PPC64_GOT_TLSGD34:
     case elfcpp::R_POWERPC_GOT_TLSGD16:
     case elfcpp::R_POWERPC_GOT_TLSGD16_LO:
     case elfcpp::R_POWERPC_GOT_TLSGD16_HI:
@@ -7862,6 +7908,7 @@ Target_powerpc<size, big_endian>::Scan::local(
       }
       break;
 
+    case elfcpp::R_PPC64_GOT_TLSLD34:
     case elfcpp::R_POWERPC_GOT_TLSLD16:
     case elfcpp::R_POWERPC_GOT_TLSLD16_LO:
     case elfcpp::R_POWERPC_GOT_TLSLD16_HI:
@@ -7885,6 +7932,7 @@ Target_powerpc<size, big_endian>::Scan::local(
       }
       break;
 
+    case elfcpp::R_PPC64_GOT_DTPREL34:
     case elfcpp::R_POWERPC_GOT_DTPREL16:
     case elfcpp::R_POWERPC_GOT_DTPREL16_LO:
     case elfcpp::R_POWERPC_GOT_DTPREL16_HI:
@@ -7897,6 +7945,7 @@ Target_powerpc<size, big_endian>::Scan::local(
       }
       break;
 
+    case elfcpp::R_PPC64_GOT_TPREL34:
     case elfcpp::R_POWERPC_GOT_TPREL16:
     case elfcpp::R_POWERPC_GOT_TPREL16_LO:
     case elfcpp::R_POWERPC_GOT_TPREL16_HI:
@@ -8088,6 +8137,52 @@ Target_powerpc<size, big_endian>::Scan::local(
     case elfcpp::R_PPC64_TOC16:
     case elfcpp::R_PPC64_TOC16_DS:
       ppc_object->set_has_small_toc_reloc();
+      break;
+    default:
+      break;
+    }
+
+  switch (r_type)
+    {
+    case elfcpp::R_POWERPC_TPREL16:
+    case elfcpp::R_POWERPC_TPREL16_LO:
+    case elfcpp::R_POWERPC_TPREL16_HI:
+    case elfcpp::R_POWERPC_TPREL16_HA:
+    case elfcpp::R_PPC64_TPREL16_DS:
+    case elfcpp::R_PPC64_TPREL16_LO_DS:
+    case elfcpp::R_PPC64_TPREL16_HIGH:
+    case elfcpp::R_PPC64_TPREL16_HIGHA:
+    case elfcpp::R_PPC64_TPREL16_HIGHER:
+    case elfcpp::R_PPC64_TPREL16_HIGHERA:
+    case elfcpp::R_PPC64_TPREL16_HIGHEST:
+    case elfcpp::R_PPC64_TPREL16_HIGHESTA:
+    case elfcpp::R_PPC64_TPREL34:
+      layout->set_has_static_tls();
+      break;
+    default:
+      break;
+    }
+
+  switch (r_type)
+    {
+    case elfcpp::R_PPC64_D34:
+    case elfcpp::R_PPC64_D34_LO:
+    case elfcpp::R_PPC64_D34_HI30:
+    case elfcpp::R_PPC64_D34_HA30:
+    case elfcpp::R_PPC64_D28:
+    case elfcpp::R_PPC64_PCREL34:
+    case elfcpp::R_PPC64_PCREL28:
+    case elfcpp::R_PPC64_TPREL34:
+    case elfcpp::R_PPC64_DTPREL34:
+    case elfcpp::R_PPC64_PLT_PCREL34:
+    case elfcpp::R_PPC64_PLT_PCREL34_NOTOC:
+    case elfcpp::R_PPC64_GOT_PCREL34:
+    case elfcpp::R_PPC64_GOT_TLSGD34:
+    case elfcpp::R_PPC64_GOT_TLSLD34:
+    case elfcpp::R_PPC64_GOT_DTPREL34:
+    case elfcpp::R_PPC64_GOT_TPREL34:
+      target->set_powerxx_stubs();
+      break;
     default:
       break;
     }
@@ -8184,8 +8279,6 @@ Target_powerpc<size, big_endian>::Scan::global(
     case elfcpp::R_PPC64_REL16_HIGHERA34:
     case elfcpp::R_PPC64_REL16_HIGHEST34:
     case elfcpp::R_PPC64_REL16_HIGHESTA34:
-      break;
-
     case elfcpp::R_PPC64_D34:
     case elfcpp::R_PPC64_D34_LO:
     case elfcpp::R_PPC64_D34_HI30:
@@ -8193,7 +8286,8 @@ Target_powerpc<size, big_endian>::Scan::global(
     case elfcpp::R_PPC64_D28:
     case elfcpp::R_PPC64_PCREL34:
     case elfcpp::R_PPC64_PCREL28:
-      target->set_powerxx_stubs();
+    case elfcpp::R_PPC64_TPREL34:
+    case elfcpp::R_PPC64_DTPREL34:
       break;
 
     case elfcpp::R_PPC64_TOC:
@@ -8331,8 +8425,6 @@ Target_powerpc<size, big_endian>::Scan::global(
 
     case elfcpp::R_PPC64_PLT_PCREL34:
     case elfcpp::R_PPC64_PLT_PCREL34_NOTOC:
-      target->set_powerxx_stubs();
-      // Fall through.
     case elfcpp::R_POWERPC_PLT16_LO:
     case elfcpp::R_POWERPC_PLT16_HI:
     case elfcpp::R_POWERPC_PLT16_HA:
@@ -8466,8 +8558,6 @@ Target_powerpc<size, big_endian>::Scan::global(
       break;
 
     case elfcpp::R_PPC64_GOT_PCREL34:
-      target->set_powerxx_stubs();
-      // Fall through.
     case elfcpp::R_POWERPC_GOT16:
     case elfcpp::R_POWERPC_GOT16_LO:
     case elfcpp::R_POWERPC_GOT16_HI:
@@ -8526,6 +8616,7 @@ Target_powerpc<size, big_endian>::Scan::global(
       target->got_section(symtab, layout);
       break;
 
+    case elfcpp::R_PPC64_GOT_TLSGD34:
     case elfcpp::R_POWERPC_GOT_TLSGD16:
     case elfcpp::R_POWERPC_GOT_TLSGD16_LO:
     case elfcpp::R_POWERPC_GOT_TLSGD16_HI:
@@ -8574,6 +8665,7 @@ Target_powerpc<size, big_endian>::Scan::global(
       }
       break;
 
+    case elfcpp::R_PPC64_GOT_TLSLD34:
     case elfcpp::R_POWERPC_GOT_TLSLD16:
     case elfcpp::R_POWERPC_GOT_TLSLD16_LO:
     case elfcpp::R_POWERPC_GOT_TLSLD16_HI:
@@ -8597,6 +8689,7 @@ Target_powerpc<size, big_endian>::Scan::global(
       }
       break;
 
+    case elfcpp::R_PPC64_GOT_DTPREL34:
     case elfcpp::R_POWERPC_GOT_DTPREL16:
     case elfcpp::R_POWERPC_GOT_DTPREL16_LO:
     case elfcpp::R_POWERPC_GOT_DTPREL16_HI:
@@ -8616,6 +8709,7 @@ Target_powerpc<size, big_endian>::Scan::global(
       }
       break;
 
+    case elfcpp::R_PPC64_GOT_TPREL34:
     case elfcpp::R_POWERPC_GOT_TPREL16:
     case elfcpp::R_POWERPC_GOT_TPREL16_LO:
     case elfcpp::R_POWERPC_GOT_TPREL16_HI:
@@ -8801,6 +8895,52 @@ Target_powerpc<size, big_endian>::Scan::global(
     case elfcpp::R_PPC64_TOC16:
     case elfcpp::R_PPC64_TOC16_DS:
       ppc_object->set_has_small_toc_reloc();
+      break;
+    default:
+      break;
+    }
+
+  switch (r_type)
+    {
+    case elfcpp::R_POWERPC_TPREL16:
+    case elfcpp::R_POWERPC_TPREL16_LO:
+    case elfcpp::R_POWERPC_TPREL16_HI:
+    case elfcpp::R_POWERPC_TPREL16_HA:
+    case elfcpp::R_PPC64_TPREL16_DS:
+    case elfcpp::R_PPC64_TPREL16_LO_DS:
+    case elfcpp::R_PPC64_TPREL16_HIGH:
+    case elfcpp::R_PPC64_TPREL16_HIGHA:
+    case elfcpp::R_PPC64_TPREL16_HIGHER:
+    case elfcpp::R_PPC64_TPREL16_HIGHERA:
+    case elfcpp::R_PPC64_TPREL16_HIGHEST:
+    case elfcpp::R_PPC64_TPREL16_HIGHESTA:
+    case elfcpp::R_PPC64_TPREL34:
+      layout->set_has_static_tls();
+      break;
+    default:
+      break;
+    }
+
+  switch (r_type)
+    {
+    case elfcpp::R_PPC64_D34:
+    case elfcpp::R_PPC64_D34_LO:
+    case elfcpp::R_PPC64_D34_HI30:
+    case elfcpp::R_PPC64_D34_HA30:
+    case elfcpp::R_PPC64_D28:
+    case elfcpp::R_PPC64_PCREL34:
+    case elfcpp::R_PPC64_PCREL28:
+    case elfcpp::R_PPC64_TPREL34:
+    case elfcpp::R_PPC64_DTPREL34:
+    case elfcpp::R_PPC64_PLT_PCREL34:
+    case elfcpp::R_PPC64_PLT_PCREL34_NOTOC:
+    case elfcpp::R_PPC64_GOT_PCREL34:
+    case elfcpp::R_PPC64_GOT_TLSGD34:
+    case elfcpp::R_PPC64_GOT_TLSLD34:
+    case elfcpp::R_PPC64_GOT_DTPREL34:
+    case elfcpp::R_PPC64_GOT_TPREL34:
+      target->set_powerxx_stubs();
+      break;
     default:
       break;
     }
@@ -9660,6 +9800,145 @@ Target_powerpc<size, big_endian>::symval_for_branch(
   return true;
 }
 
+template<int size>
+static bool
+relative_value_is_known(const Sized_symbol<size>* gsym)
+{
+  if (gsym->type() == elfcpp::STT_GNU_IFUNC)
+    return false;
+
+  if (gsym->is_from_dynobj()
+      || gsym->is_undefined()
+      || gsym->is_preemptible())
+    return false;
+
+  if (gsym->is_absolute())
+    return !parameters->options().output_is_position_independent();
+
+  return true;
+}
+
+template<int size>
+static bool
+relative_value_is_known(const Symbol_value<size>* psymval)
+{
+  if (psymval->is_ifunc_symbol())
+    return false;
+
+  bool is_ordinary;
+  unsigned int shndx = psymval->input_shndx(&is_ordinary);
+
+  return is_ordinary && shndx != elfcpp::SHN_UNDEF;
+}
+
+// PCREL_OPT in one instance flags to the linker that a pair of insns:
+//   pld ra,symbol@got@pcrel
+//   load/store rt,0(ra)
+// or
+//   pla ra,symbol@pcrel
+//   load/store rt,0(ra)
+// may be translated to
+//   pload/pstore rt,symbol@pcrel
+//   nop.
+// This function returns true if the optimization is possible, placing
+// the prefix insn in *PINSN1 and a NOP in *PINSN2.
+//
+// On entry to this function, the linker has already determined that
+// the pld can be replaced with pla: *PINSN1 is that pla insn,
+// while *PINSN2 is the second instruction.
+
+inline bool
+xlate_pcrel_opt(uint64_t *pinsn1, uint64_t *pinsn2)
+{
+  uint32_t insn2 = *pinsn2 >> 32;
+  uint64_t i1new;
+
+  // Check that regs match.
+  if (((insn2 >> 16) & 31) != ((*pinsn1 >> 21) & 31))
+    return false;
+
+  switch ((insn2 >> 26) & 63)
+    {
+    default:
+      return false;
+
+    case 32: // lwz
+    case 34: // lbz
+    case 36: // stw
+    case 38: // stb
+    case 40: // lhz
+    case 42: // lha
+    case 44: // sth
+    case 48: // lfs
+    case 50: // lfd
+    case 52: // stfs
+    case 54: // stfd
+      // These are the PMLS cases, where we just need to tack a prefix
+      // on the insn.  Check that the D field is zero.
+      if ((insn2 & 0xffff) != 0)
+       return false;
+      i1new = ((1ULL << 58) | (2ULL << 56) | (1ULL << 52)
+              | (insn2 & ((63ULL << 26) | (31ULL << 21))));
+      break;
+
+    case 58: // lwa, ld
+      if ((insn2 & 0xfffd) != 0)
+       return false;
+      i1new = ((1ULL << 58) | (1ULL << 52)
+              | (insn2 & 2 ? 41ULL << 26 : 57ULL << 26)
+              | (insn2 & (31ULL << 21)));
+      break;
+
+    case 57: // lxsd, lxssp
+      if ((insn2 & 0xfffc) != 0 || (insn2 & 3) < 2)
+       return false;
+      i1new = ((1ULL << 58) | (1ULL << 52)
+              | ((40ULL | (insn2 & 3)) << 26)
+              | (insn2 & (31ULL << 21)));
+      break;
+
+    case 61: // stxsd, stxssp, lxv, stxv
+      if ((insn2 & 3) == 0)
+       return false;
+      else if ((insn2 & 3) >= 2)
+       {
+         if ((insn2 & 0xfffc) != 0)
+           return false;
+         i1new = ((1ULL << 58) | (1ULL << 52)
+                  | ((44ULL | (insn2 & 3)) << 26)
+                  | (insn2 & (31ULL << 21)));
+       }
+      else
+       {
+         if ((insn2 & 0xfff0) != 0)
+           return false;
+         i1new = ((1ULL << 58) | (1ULL << 52)
+                  | ((50ULL | (insn2 & 4) | ((insn2 & 8) >> 3)) << 26)
+                  | (insn2 & (31ULL << 21)));
+       }
+      break;
+
+    case 56: // lq
+      if ((insn2 & 0xffff) != 0)
+       return false;
+      i1new = ((1ULL << 58) | (1ULL << 52)
+              | (insn2 & ((63ULL << 26) | (31ULL << 21))));
+      break;
+
+    case 62: // std, stq
+      if ((insn2 & 0xfffd) != 0)
+       return false;
+      i1new = ((1ULL << 58) | (1ULL << 52)
+              | ((insn2 & 2) == 0 ? 61ULL << 26 : 60ULL << 26)
+              | (insn2 & (31ULL << 21)));
+      break;
+    }
+
+  *pinsn1 = i1new;
+  *pinsn2 = (uint64_t) nop << 32;
+  return true;
+}
+
 // Perform a relocation.
 
 template<int size, bool big_endian>
@@ -9969,7 +10248,8 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
   else if (r_type == elfcpp::R_POWERPC_GOT_TLSGD16
           || r_type == elfcpp::R_POWERPC_GOT_TLSGD16_LO
           || r_type == elfcpp::R_POWERPC_GOT_TLSGD16_HI
-          || r_type == elfcpp::R_POWERPC_GOT_TLSGD16_HA)
+          || r_type == elfcpp::R_POWERPC_GOT_TLSGD16_HA
+          || r_type == elfcpp::R_PPC64_GOT_TLSGD34)
     {
       // First instruction of a global dynamic sequence, arg setup insn.
       const bool final = gsym == NULL || gsym->final_value_is_known();
@@ -9991,67 +10271,121 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
              gold_assert(object->local_has_got_offset(r_sym, got_type));
              value = object->local_got_offset(r_sym, got_type);
            }
-         value -= target->got_section()->got_base_offset(object);
+         if (r_type == elfcpp::R_PPC64_GOT_TLSGD34)
+           value += target->got_section()->address();
+         else
+           value -= target->got_section()->got_base_offset(object);
        }
       if (tls_type == tls::TLSOPT_TO_IE)
        {
-         if (r_type == elfcpp::R_POWERPC_GOT_TLSGD16
-             || r_type == elfcpp::R_POWERPC_GOT_TLSGD16_LO)
+         if (r_type == elfcpp::R_PPC64_GOT_TLSGD34)
            {
-             Insn* iview = reinterpret_cast<Insn*>(view - d_offset);
-             Insn insn = elfcpp::Swap<32, big_endian>::readval(iview);
-             insn &= (1 << 26) - (1 << 16); // extract rt,ra from addi
-             if (size == 32)
-               insn |= 32 << 26; // lwz
-             else
-               insn |= 58 << 26; // ld
-             elfcpp::Swap<32, big_endian>::writeval(iview, insn);
+             Insn* iview = reinterpret_cast<Insn*>(view);
+             uint64_t pinsn = elfcpp::Swap<32, big_endian>::readval(iview);
+             pinsn <<= 32;
+             pinsn |= elfcpp::Swap<32, big_endian>::readval(iview + 1);
+             // pla -> pld
+             pinsn += (-2ULL << 56) + (57ULL << 26) - (14ULL << 26);
+             elfcpp::Swap<32, big_endian>::writeval(iview, pinsn >> 32);
+             elfcpp::Swap<32, big_endian>::writeval(iview + 1,
+                                                    pinsn & 0xffffffff);
+             r_type = elfcpp::R_PPC64_GOT_TPREL34;
+           }
+         else
+           {
+             if (r_type == elfcpp::R_POWERPC_GOT_TLSGD16
+                 || r_type == elfcpp::R_POWERPC_GOT_TLSGD16_LO)
+               {
+                 Insn* iview = reinterpret_cast<Insn*>(view - d_offset);
+                 Insn insn = elfcpp::Swap<32, big_endian>::readval(iview);
+                 insn &= (1 << 26) - (1 << 16); // extract rt,ra from addi
+                 if (size == 32)
+                   insn |= 32 << 26; // lwz
+                 else
+                   insn |= 58 << 26; // ld
+                 elfcpp::Swap<32, big_endian>::writeval(iview, insn);
+               }
+             r_type += (elfcpp::R_POWERPC_GOT_TPREL16
+                        - elfcpp::R_POWERPC_GOT_TLSGD16);
            }
-         r_type += (elfcpp::R_POWERPC_GOT_TPREL16
-                    - elfcpp::R_POWERPC_GOT_TLSGD16);
        }
       else if (tls_type == tls::TLSOPT_TO_LE)
        {
-         if (r_type == elfcpp::R_POWERPC_GOT_TLSGD16
-             || r_type == elfcpp::R_POWERPC_GOT_TLSGD16_LO)
+         if (r_type == elfcpp::R_PPC64_GOT_TLSGD34)
            {
-             Insn* iview = reinterpret_cast<Insn*>(view - d_offset);
-             Insn insn = elfcpp::Swap<32, big_endian>::readval(iview);
-             insn &= (1 << 26) - (1 << 21); // extract rt
-             if (size == 32)
-               insn |= addis_0_2;
-             else
-               insn |= addis_0_13;
-             elfcpp::Swap<32, big_endian>::writeval(iview, insn);
-             r_type = elfcpp::R_POWERPC_TPREL16_HA;
+             Insn* iview = reinterpret_cast<Insn*>(view);
+             uint64_t pinsn = elfcpp::Swap<32, big_endian>::readval(iview);
+             pinsn <<= 32;
+             pinsn |= elfcpp::Swap<32, big_endian>::readval(iview + 1);
+             // pla pcrel -> paddi r13
+             pinsn += (-1ULL << 52) + (13ULL << 16);
+             elfcpp::Swap<32, big_endian>::writeval(iview, pinsn >> 32);
+             elfcpp::Swap<32, big_endian>::writeval(iview + 1,
+                                                    pinsn & 0xffffffff);
+             r_type = elfcpp::R_PPC64_TPREL34;
              value = psymval->value(object, rela.get_r_addend());
            }
          else
            {
-             Insn* iview = reinterpret_cast<Insn*>(view - d_offset);
-             Insn insn = nop;
-             elfcpp::Swap<32, big_endian>::writeval(iview, insn);
-             r_type = elfcpp::R_POWERPC_NONE;
+             if (r_type == elfcpp::R_POWERPC_GOT_TLSGD16
+                 || r_type == elfcpp::R_POWERPC_GOT_TLSGD16_LO)
+               {
+                 Insn* iview = reinterpret_cast<Insn*>(view - d_offset);
+                 Insn insn = elfcpp::Swap<32, big_endian>::readval(iview);
+                 insn &= (1 << 26) - (1 << 21); // extract rt
+                 if (size == 32)
+                   insn |= addis_0_2;
+                 else
+                   insn |= addis_0_13;
+                 elfcpp::Swap<32, big_endian>::writeval(iview, insn);
+                 r_type = elfcpp::R_POWERPC_TPREL16_HA;
+                 value = psymval->value(object, rela.get_r_addend());
+               }
+             else
+               {
+                 Insn* iview = reinterpret_cast<Insn*>(view - d_offset);
+                 Insn insn = nop;
+                 elfcpp::Swap<32, big_endian>::writeval(iview, insn);
+                 r_type = elfcpp::R_POWERPC_NONE;
+               }
            }
        }
     }
   else if (r_type == elfcpp::R_POWERPC_GOT_TLSLD16
           || r_type == elfcpp::R_POWERPC_GOT_TLSLD16_LO
           || r_type == elfcpp::R_POWERPC_GOT_TLSLD16_HI
-          || r_type == elfcpp::R_POWERPC_GOT_TLSLD16_HA)
+          || r_type == elfcpp::R_POWERPC_GOT_TLSLD16_HA
+          || r_type == elfcpp::R_PPC64_GOT_TLSLD34)
     {
       // First instruction of a local dynamic sequence, arg setup insn.
       const tls::Tls_optimization tls_type = target->optimize_tls_ld();
       if (tls_type == tls::TLSOPT_NONE)
        {
          value = target->tlsld_got_offset();
-         value -= target->got_section()->got_base_offset(object);
+         if (r_type == elfcpp::R_PPC64_GOT_TLSLD34)
+           value += target->got_section()->address();
+         else
+           value -= target->got_section()->got_base_offset(object);
        }
       else
        {
          gold_assert(tls_type == tls::TLSOPT_TO_LE);
-         if (r_type == elfcpp::R_POWERPC_GOT_TLSLD16
-             || r_type == elfcpp::R_POWERPC_GOT_TLSLD16_LO)
+         if (r_type == elfcpp::R_PPC64_GOT_TLSLD34)
+           {
+             Insn* iview = reinterpret_cast<Insn*>(view);
+             uint64_t pinsn = elfcpp::Swap<32, big_endian>::readval(iview);
+             pinsn <<= 32;
+             pinsn |= elfcpp::Swap<32, big_endian>::readval(iview + 1);
+             // pla pcrel -> paddi r13
+             pinsn += (-1ULL << 52) + (13ULL << 16);
+             elfcpp::Swap<32, big_endian>::writeval(iview, pinsn >> 32);
+             elfcpp::Swap<32, big_endian>::writeval(iview + 1,
+                                                    pinsn & 0xffffffff);
+             r_type = elfcpp::R_PPC64_TPREL34;
+             value = dtp_offset;
+           }
+         else if (r_type == elfcpp::R_POWERPC_GOT_TLSLD16
+                  || r_type == elfcpp::R_POWERPC_GOT_TLSLD16_LO)
            {
              Insn* iview = reinterpret_cast<Insn*>(view - d_offset);
              Insn insn = elfcpp::Swap<32, big_endian>::readval(iview);
@@ -10076,7 +10410,8 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
   else if (r_type == elfcpp::R_POWERPC_GOT_DTPREL16
           || r_type == elfcpp::R_POWERPC_GOT_DTPREL16_LO
           || r_type == elfcpp::R_POWERPC_GOT_DTPREL16_HI
-          || r_type == elfcpp::R_POWERPC_GOT_DTPREL16_HA)
+          || r_type == elfcpp::R_POWERPC_GOT_DTPREL16_HA
+          || r_type == elfcpp::R_PPC64_GOT_DTPREL34)
     {
       // Accesses relative to a local dynamic sequence address,
       // no optimisation here.
@@ -10090,12 +10425,16 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
          gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_DTPREL));
          value = object->local_got_offset(r_sym, GOT_TYPE_DTPREL);
        }
-      value -= target->got_section()->got_base_offset(object);
+      if (r_type == elfcpp::R_PPC64_GOT_DTPREL34)
+       value += target->got_section()->address();
+      else
+       value -= target->got_section()->got_base_offset(object);
     }
   else if (r_type == elfcpp::R_POWERPC_GOT_TPREL16
           || r_type == elfcpp::R_POWERPC_GOT_TPREL16_LO
           || r_type == elfcpp::R_POWERPC_GOT_TPREL16_HI
-          || r_type == elfcpp::R_POWERPC_GOT_TPREL16_HA)
+          || r_type == elfcpp::R_POWERPC_GOT_TPREL16_HA
+          || r_type == elfcpp::R_PPC64_GOT_TPREL34)
     {
       // First instruction of initial exec sequence.
       const bool final = gsym == NULL || gsym->final_value_is_known();
@@ -10112,13 +10451,31 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
              gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_TPREL));
              value = object->local_got_offset(r_sym, GOT_TYPE_TPREL);
            }
-         value -= target->got_section()->got_base_offset(object);
+         if (r_type == elfcpp::R_PPC64_GOT_TPREL34)
+           value += target->got_section()->address();
+         else
+           value -= target->got_section()->got_base_offset(object);
        }
       else
        {
          gold_assert(tls_type == tls::TLSOPT_TO_LE);
-         if (r_type == elfcpp::R_POWERPC_GOT_TPREL16
-             || r_type == elfcpp::R_POWERPC_GOT_TPREL16_LO)
+         if (r_type == elfcpp::R_PPC64_GOT_TPREL34)
+           {
+             Insn* iview = reinterpret_cast<Insn*>(view);
+             uint64_t pinsn = elfcpp::Swap<32, big_endian>::readval(iview);
+             pinsn <<= 32;
+             pinsn |= elfcpp::Swap<32, big_endian>::readval(iview + 1);
+             // pld ra,sym@got@tprel@pcrel -> paddi ra,r13,sym@tprel
+             pinsn += ((2ULL << 56) + (-1ULL << 52)
+                       + (14ULL << 26) - (57ULL << 26) + (13ULL << 16));
+             elfcpp::Swap<32, big_endian>::writeval(iview, pinsn >> 32);
+             elfcpp::Swap<32, big_endian>::writeval(iview + 1,
+                                                    pinsn & 0xffffffff);
+             r_type = elfcpp::R_PPC64_TPREL34;
+             value = psymval->value(object, rela.get_r_addend());
+           }
+         else if (r_type == elfcpp::R_POWERPC_GOT_TPREL16
+                  || r_type == elfcpp::R_POWERPC_GOT_TPREL16_LO)
            {
              Insn* iview = reinterpret_cast<Insn*>(view - d_offset);
              Insn insn = elfcpp::Swap<32, big_endian>::readval(iview);
@@ -10161,12 +10518,33 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
            }
          else
            {
+             bool is_pcrel = false;
+             const int reloc_size = elfcpp::Elf_sizes<size>::rela_size;
+             elfcpp::Shdr<size, big_endian> shdr(relinfo->reloc_shdr);
+             size_t reloc_count = shdr.get_sh_size() / reloc_size;
+             if (relnum < reloc_count - 1)
+               {
+                 Reltype next_rela(preloc + reloc_size);
+                 unsigned int r_type2
+                   = elfcpp::elf_r_type<size>(next_rela.get_r_info());
+                 if ((r_type2 == elfcpp::R_PPC64_REL24_NOTOC
+                      || r_type2 == elfcpp::R_PPC64_PLTCALL_NOTOC)
+                     && next_rela.get_r_offset() == rela.get_r_offset())
+                   is_pcrel = true;
+               }
              Insn* iview = reinterpret_cast<Insn*>(view);
-             Insn insn = addi_3_3;
-             elfcpp::Swap<32, big_endian>::writeval(iview, insn);
-             r_type = elfcpp::R_POWERPC_TPREL16_LO;
-             view += d_offset;
-             value = psymval->value(object, rela.get_r_addend());
+             if (is_pcrel)
+               {
+                 elfcpp::Swap<32, big_endian>::writeval(iview, nop);
+                 r_type = elfcpp::R_POWERPC_NONE;
+               }
+             else
+               {
+                 elfcpp::Swap<32, big_endian>::writeval(iview, addi_3_3);
+                 r_type = elfcpp::R_POWERPC_TPREL16_LO;
+                 view += d_offset;
+                 value = psymval->value(object, rela.get_r_addend());
+               }
            }
          this->skip_next_tls_get_addr_call();
        }
@@ -10180,13 +10558,34 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
       const tls::Tls_optimization tls_type = target->optimize_tls_ld();
       if (tls_type == tls::TLSOPT_TO_LE)
        {
+         bool is_pcrel = false;
+         const int reloc_size = elfcpp::Elf_sizes<size>::rela_size;
+         elfcpp::Shdr<size, big_endian> shdr(relinfo->reloc_shdr);
+         size_t reloc_count = shdr.get_sh_size() / reloc_size;
+         if (relnum < reloc_count - 1)
+           {
+             Reltype next_rela(preloc + reloc_size);
+             unsigned int r_type2
+               = elfcpp::elf_r_type<size>(next_rela.get_r_info());
+             if ((r_type2 == elfcpp::R_PPC64_REL24_NOTOC
+                  || r_type2 == elfcpp::R_PPC64_PLTCALL_NOTOC)
+                 && next_rela.get_r_offset() == rela.get_r_offset())
+               is_pcrel = true;
+           }
          Insn* iview = reinterpret_cast<Insn*>(view);
-         Insn insn = addi_3_3;
-         elfcpp::Swap<32, big_endian>::writeval(iview, insn);
+         if (is_pcrel)
+           {
+             elfcpp::Swap<32, big_endian>::writeval(iview, nop);
+             r_type = elfcpp::R_POWERPC_NONE;
+           }
+         else
+           {
+             elfcpp::Swap<32, big_endian>::writeval(iview, addi_3_3);
+             r_type = elfcpp::R_POWERPC_TPREL16_LO;
+             view += d_offset;
+             value = dtp_offset;
+           }
          this->skip_next_tls_get_addr_call();
-         r_type = elfcpp::R_POWERPC_TPREL16_LO;
-         view += d_offset;
-         value = dtp_offset;
        }
     }
   else if (r_type == elfcpp::R_POWERPC_TLS)
@@ -10196,15 +10595,40 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
       const tls::Tls_optimization tls_type = target->optimize_tls_ie(final);
       if (tls_type == tls::TLSOPT_TO_LE)
        {
-         Insn* iview = reinterpret_cast<Insn*>(view);
+         Address roff = rela.get_r_offset() & 3;
+         Insn* iview = reinterpret_cast<Insn*>(view - roff);
          Insn insn = elfcpp::Swap<32, big_endian>::readval(iview);
          unsigned int reg = size == 32 ? 2 : 13;
          insn = at_tls_transform(insn, reg);
          gold_assert(insn != 0);
-         elfcpp::Swap<32, big_endian>::writeval(iview, insn);
-         r_type = elfcpp::R_POWERPC_TPREL16_LO;
-         view += d_offset;
-         value = psymval->value(object, rela.get_r_addend());
+         if (roff == 0)
+           {
+             elfcpp::Swap<32, big_endian>::writeval(iview, insn);
+             r_type = elfcpp::R_POWERPC_TPREL16_LO;
+             view += d_offset;
+             value = psymval->value(object, rela.get_r_addend());
+           }
+         else if (roff == 1)
+           {
+             // For pcrel IE to LE we already have the full offset
+             // and thus don't need an addi here.  A nop or mr will do.
+             if ((insn & (0x3f << 26)) == 14 << 26)
+               {
+                 // Extract regs from addi rt,ra,si.
+                 unsigned int rt = (insn >> 21) & 0x1f;
+                 unsigned int ra = (insn >> 16) & 0x1f;
+                 if (rt == ra)
+                   insn = nop;
+                 else
+                   {
+                     // Build or ra,rs,rb with rb==rs, ie. mr ra,rs.
+                     insn = (rt << 16) | (ra << 21) | (ra << 11);
+                     insn |= (31u << 26) | (444u << 1);
+                   }
+               }
+             elfcpp::Swap<32, big_endian>::writeval(iview, insn);
+             r_type = elfcpp::R_POWERPC_NONE;
+           }
        }
     }
   else if (!has_stub_value)
@@ -10307,6 +10731,10 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
     case elfcpp::R_PPC64_PLT_PCREL34:
     case elfcpp::R_PPC64_PLT_PCREL34_NOTOC:
     case elfcpp::R_PPC64_PCREL28:
+    case elfcpp::R_PPC64_GOT_TLSGD34:
+    case elfcpp::R_PPC64_GOT_TLSLD34:
+    case elfcpp::R_PPC64_GOT_TPREL34:
+    case elfcpp::R_PPC64_GOT_DTPREL34:
     case elfcpp::R_PPC64_REL16_HIGHER34:
     case elfcpp::R_PPC64_REL16_HIGHERA34:
     case elfcpp::R_PPC64_REL16_HIGHEST34:
@@ -10352,6 +10780,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
     case elfcpp::R_PPC64_TPREL16_HIGHERA:
     case elfcpp::R_PPC64_TPREL16_HIGHEST:
     case elfcpp::R_PPC64_TPREL16_HIGHESTA:
+    case elfcpp::R_PPC64_TPREL34:
       // tls symbol values are relative to tls_segment()->vaddr()
       value -= tp_offset;
       break;
@@ -10374,6 +10803,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
     case elfcpp::R_POWERPC_DTPREL:
     case elfcpp::R_PPC64_DTPREL16_HIGH:
     case elfcpp::R_PPC64_DTPREL16_HIGHA:
+    case elfcpp::R_PPC64_DTPREL34:
       // tls symbol values are relative to tls_segment()->vaddr()
       value -= dtp_offset;
       break;
@@ -10446,8 +10876,16 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
       break;
     }
 
-  if (size == 64)
+  if (size == 64
+      && (gsym
+         ? relative_value_is_known(gsym)
+         : relative_value_is_known(psymval)))
     {
+      Insn* iview;
+      Insn* iview2;
+      Insn insn;
+      uint64_t pinsn, pinsn2;
+
       switch (r_type)
        {
        default:
@@ -10460,12 +10898,6 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
          // and
          //     addis ra,r2,0; addi rb,ra,x@toc@l;
          // to  nop;           addi rb,r2,x@toc;
-         // FIXME: the @got sequence shown above is not yet
-         // optimized.  Note that gcc as of 2017-01-07 doesn't use
-         // the ELF @got relocs except for TLS, instead using the
-         // PowerOpen variant of a compiler managed GOT (called TOC).
-         // The PowerOpen TOC sequence equivalent to the first
-         // example is optimized.
        case elfcpp::R_POWERPC_GOT_TLSLD16_HA:
        case elfcpp::R_POWERPC_GOT_TLSGD16_HA:
        case elfcpp::R_POWERPC_GOT_TPREL16_HA:
@@ -10474,10 +10906,14 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
        case elfcpp::R_PPC64_TOC16_HA:
          if (parameters->options().toc_optimize())
            {
-             Insn* iview = reinterpret_cast<Insn*>(view - d_offset);
-             Insn insn = elfcpp::Swap<32, big_endian>::readval(iview);
-             if (r_type == elfcpp::R_PPC64_TOC16_HA
-                 && object->make_toc_relative(target, &value))
+             iview = reinterpret_cast<Insn*>(view - d_offset);
+             insn = elfcpp::Swap<32, big_endian>::readval(iview);
+             if ((r_type == elfcpp::R_PPC64_TOC16_HA
+                  && object->make_toc_relative(target, &value))
+                 || (r_type == elfcpp::R_POWERPC_GOT16_HA
+                     && object->make_got_relative(target, psymval,
+                                                  rela.get_r_addend(),
+                                                  &value)))
                {
                  gold_assert((insn & ((0x3f << 26) | 0x1f << 16))
                              == ((15u << 26) | (2 << 16)));
@@ -10502,11 +10938,15 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
        case elfcpp::R_PPC64_TOC16_LO_DS:
          if (parameters->options().toc_optimize())
            {
-             Insn* iview = reinterpret_cast<Insn*>(view - d_offset);
-             Insn insn = elfcpp::Swap<32, big_endian>::readval(iview);
+             iview = reinterpret_cast<Insn*>(view - d_offset);
+             insn = elfcpp::Swap<32, big_endian>::readval(iview);
              bool changed = false;
-             if (r_type == elfcpp::R_PPC64_TOC16_LO_DS
-                 && object->make_toc_relative(target, &value))
+             if ((r_type == elfcpp::R_PPC64_TOC16_LO_DS
+                  && object->make_toc_relative(target, &value))
+                 || (r_type == elfcpp::R_PPC64_GOT16_LO_DS
+                     && object->make_got_relative(target, psymval,
+                                                  rela.get_r_addend(),
+                                                  &value)))
                {
                  gold_assert ((insn & (0x3f << 26)) == 58u << 26 /* ld */);
                  insn ^= (14u << 26) ^ (58u << 26);
@@ -10534,6 +10974,77 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
            }
          break;
 
+       case elfcpp::R_PPC64_GOT_PCREL34:
+         if (parameters->options().toc_optimize())
+           {
+             iview = reinterpret_cast<Insn*>(view);
+             pinsn = elfcpp::Swap<32, big_endian>::readval(iview);
+             pinsn <<= 32;
+             pinsn |= elfcpp::Swap<32, big_endian>::readval(iview + 1);
+             if ((pinsn & ((-1ULL << 50) | (63ULL << 26)))
+                  != ((1ULL << 58) | (1ULL << 52) | (57ULL << 26) /* pld */))
+               break;
+
+             Address relval = psymval->value(object, rela.get_r_addend());
+             relval -= address;
+             if (relval + (1ULL << 33) < 1ULL << 34)
+               {
+                 value = relval;
+                 // Replace with paddi
+                 pinsn += (2ULL << 56) + (14ULL << 26) - (57ULL << 26);
+                 elfcpp::Swap<32, big_endian>::writeval(iview, pinsn >> 32);
+                 elfcpp::Swap<32, big_endian>::writeval(iview + 1,
+                                                        pinsn & 0xffffffff);
+                 goto pcrelopt;
+               }
+           }
+         break;
+
+       case elfcpp::R_PPC64_PCREL34:
+         {
+           iview = reinterpret_cast<Insn*>(view);
+           pinsn = elfcpp::Swap<32, big_endian>::readval(iview);
+           pinsn <<= 32;
+           pinsn |= elfcpp::Swap<32, big_endian>::readval(iview + 1);
+           if ((pinsn & ((-1ULL << 50) | (63ULL << 26)))
+               != ((1ULL << 58) | (2ULL << 56) | (1ULL << 52)
+                   | (14ULL << 26) /* paddi */))
+             break;
+
+         pcrelopt:
+           const int reloc_size = elfcpp::Elf_sizes<size>::rela_size;
+           elfcpp::Shdr<size, big_endian> shdr(relinfo->reloc_shdr);
+           size_t reloc_count = shdr.get_sh_size() / reloc_size;
+           if (relnum >= reloc_count - 1)
+             break;
+
+           Reltype next_rela(preloc + reloc_size);
+           if ((elfcpp::elf_r_type<size>(next_rela.get_r_info())
+                != elfcpp::R_PPC64_PCREL_OPT)
+               || next_rela.get_r_offset() != rela.get_r_offset())
+             break;
+
+           Address off = next_rela.get_r_addend();
+           if (off == 0)
+             off = 8; // zero means next insn.
+           if (off + rela.get_r_offset() + 4 > view_size)
+             break;
+
+           iview2 = reinterpret_cast<Insn*>(view + off);
+           pinsn2 = elfcpp::Swap<32, big_endian>::readval(iview2);
+           pinsn2 <<= 32;
+           if ((pinsn2 & (63ULL << 58)) == 1ULL << 58)
+             break;
+           if (xlate_pcrel_opt(&pinsn, &pinsn2))
+             {
+               elfcpp::Swap<32, big_endian>::writeval(iview, pinsn >> 32);
+               elfcpp::Swap<32, big_endian>::writeval(iview + 1,
+                                                      pinsn & 0xffffffff);
+               elfcpp::Swap<32, big_endian>::writeval(iview2, pinsn2 >> 32);
+             }
+         }
+         break;
+
        case elfcpp::R_POWERPC_TPREL16_HA:
          if (parameters->options().tls_optimize() && value + 0x8000 < 0x10000)
            {
@@ -10758,6 +11269,12 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
     case elfcpp::R_PPC64_PLT_PCREL34_NOTOC:
     case elfcpp::R_PPC64_D28:
     case elfcpp::R_PPC64_PCREL28:
+    case elfcpp::R_PPC64_TPREL34:
+    case elfcpp::R_PPC64_DTPREL34:
+    case elfcpp::R_PPC64_GOT_TLSGD34:
+    case elfcpp::R_PPC64_GOT_TLSLD34:
+    case elfcpp::R_PPC64_GOT_TPREL34:
+    case elfcpp::R_PPC64_GOT_DTPREL34:
       overflow = Reloc::CHECK_SIGNED;
       break;
     }
@@ -11054,6 +11571,12 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
     case elfcpp::R_PPC64_GOT_PCREL34:
     case elfcpp::R_PPC64_PLT_PCREL34:
     case elfcpp::R_PPC64_PLT_PCREL34_NOTOC:
+    case elfcpp::R_PPC64_TPREL34:
+    case elfcpp::R_PPC64_DTPREL34:
+    case elfcpp::R_PPC64_GOT_TLSGD34:
+    case elfcpp::R_PPC64_GOT_TLSLD34:
+    case elfcpp::R_PPC64_GOT_TPREL34:
+    case elfcpp::R_PPC64_GOT_DTPREL34:
       if (size == 32)
        goto unsupp;
       status = Reloc::addr34(view, value, overflow);
This page took 0.03508 seconds and 4 git commands to generate.