Index PowerPC64 linker generated .eh_frame in .eh_frame_hdr
[deliverable/binutils-gdb.git] / bfd / elf64-ppc.c
index 581ce55f309b3b06df1f5a33d64631b0167f1f76..2b9b07ecf6df5b2d3126ed7fc7224c4fa6503b6e 100644 (file)
@@ -235,6 +235,19 @@ static bfd_vma opd_entry_value
 #ifndef NO_OPD_RELOCS
 #define NO_OPD_RELOCS 0
 #endif
+
+static inline int
+abiversion (bfd *abfd)
+{
+  return elf_elfheader (abfd)->e_flags & EF_PPC64_ABI;
+}
+
+static inline void
+set_abiversion (bfd *abfd, int ver)
+{
+  elf_elfheader (abfd)->e_flags &= ~EF_PPC64_ABI;
+  elf_elfheader (abfd)->e_flags |= ver & EF_PPC64_ABI;
+}
 \f
 #define ONES(n) (((bfd_vma) 1 << ((n) - 1) << 1) - 1)
 
@@ -2487,6 +2500,29 @@ ppc64_elf_branch_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
                                      + symbol->section->output_section->vma
                                      + symbol->section->output_offset);
     }
+  else
+    {
+      elf_symbol_type *elfsym = (elf_symbol_type *) symbol;
+
+      if (symbol->section->owner != abfd
+         && abiversion (symbol->section->owner) >= 2)
+       {
+         unsigned int i;
+
+         for (i = 0; i < symbol->section->owner->symcount; ++i)
+           {
+             asymbol *symdef = symbol->section->owner->outsymbols[i];
+
+             if (strcmp (symdef->name, symbol->name) == 0)
+               {
+                 elfsym = (elf_symbol_type *) symdef;
+                 break;
+               }
+           }
+       }
+      reloc_entry->addend
+       += PPC64_LOCAL_ENTRY_OFFSET (elfsym->internal_elf_sym.st_other);
+    }
   return bfd_reloc_continue;
 }
 
@@ -2975,19 +3011,6 @@ get_opd_info (asection * sec)
     return &ppc64_elf_section_data (sec)->u.opd;
   return NULL;
 }
-
-static inline int
-abiversion (bfd *abfd)
-{
-  return elf_elfheader (abfd)->e_flags & EF_PPC64_ABI;
-}
-
-static inline void
-set_abiversion (bfd *abfd, int ver)
-{
-  elf_elfheader (abfd)->e_flags &= ~EF_PPC64_ABI;
-  elf_elfheader (abfd)->e_flags |= ver & EF_PPC64_ABI;
-}
 \f
 /* Parameters for the qsort hook.  */
 static bfd_boolean synthetic_relocatable;
@@ -3762,7 +3785,8 @@ enum ppc_stub_type {
   ppc_stub_plt_branch,
   ppc_stub_plt_branch_r2off,
   ppc_stub_plt_call,
-  ppc_stub_plt_call_r2save
+  ppc_stub_plt_call_r2save,
+  ppc_stub_global_entry
 };
 
 struct ppc_stub_hash_entry {
@@ -3936,7 +3960,7 @@ struct ppc_link_hash_table
   bfd_size_type got_reli_size;
 
   /* Statistics.  */
-  unsigned long stub_count[ppc_stub_plt_call_r2save];
+  unsigned long stub_count[ppc_stub_global_entry];
 
   /* Number of stubs against global syms.  */
   unsigned long stub_globals;
@@ -4144,15 +4168,16 @@ tocsave_htab_eq (const void *p1, const void *p2)
 /* Destroy a ppc64 ELF linker hash table.  */
 
 static void
-ppc64_elf_link_hash_table_free (struct bfd_link_hash_table *hash)
+ppc64_elf_link_hash_table_free (bfd *obfd)
 {
-  struct ppc_link_hash_table *htab = (struct ppc_link_hash_table *) hash;
+  struct ppc_link_hash_table *htab;
 
-  bfd_hash_table_free (&htab->stub_hash_table);
-  bfd_hash_table_free (&htab->branch_hash_table);
+  htab = (struct ppc_link_hash_table *) obfd->link.hash;
   if (htab->tocsave_htab)
     htab_delete (htab->tocsave_htab);
-  _bfd_elf_link_hash_table_free (hash);
+  bfd_hash_table_free (&htab->branch_hash_table);
+  bfd_hash_table_free (&htab->stub_hash_table);
+  _bfd_elf_link_hash_table_free (obfd);
 }
 
 /* Create a ppc64 ELF linker hash table.  */
@@ -4179,7 +4204,7 @@ ppc64_elf_link_hash_table_create (bfd *abfd)
   if (!bfd_hash_table_init (&htab->stub_hash_table, stub_hash_newfunc,
                            sizeof (struct ppc_stub_hash_entry)))
     {
-      _bfd_elf_link_hash_table_free ((struct bfd_link_hash_table *) htab);
+      _bfd_elf_link_hash_table_free (abfd);
       return NULL;
     }
 
@@ -4188,7 +4213,7 @@ ppc64_elf_link_hash_table_create (bfd *abfd)
                            sizeof (struct ppc_branch_hash_entry)))
     {
       bfd_hash_table_free (&htab->stub_hash_table);
-      _bfd_elf_link_hash_table_free ((struct bfd_link_hash_table *) htab);
+      _bfd_elf_link_hash_table_free (abfd);
       return NULL;
     }
 
@@ -4198,12 +4223,10 @@ ppc64_elf_link_hash_table_create (bfd *abfd)
                                        NULL);
   if (htab->tocsave_htab == NULL)
     {
-      bfd_hash_table_free (&htab->branch_hash_table);
-      bfd_hash_table_free (&htab->stub_hash_table);
-      _bfd_elf_link_hash_table_free ((struct bfd_link_hash_table *) htab);
+      ppc64_elf_link_hash_table_free (abfd);
       return NULL;
     }
-  (void) ppc64_elf_link_hash_table_free;
+  htab->elf.root.hash_table_free = ppc64_elf_link_hash_table_free;
 
   /* Initializing two fields of the union is just cosmetic.  We really
      only care about glist, but when compiled on a 32-bit host the
@@ -5305,7 +5328,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_GOT_TPREL16_LO_DS:
        case R_PPC64_GOT_TPREL16_HI:
        case R_PPC64_GOT_TPREL16_HA:
-         if (!info->executable)
+         if (info->shared)
            info->flags |= DF_STATIC_TLS;
          tls_type = TLS_TLS | TLS_TPREL;
          goto dogottls;
@@ -5535,7 +5558,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
        case R_PPC64_TPREL64:
          tls_type = TLS_EXPLICIT | TLS_TLS | TLS_TPREL;
-         if (!info->executable)
+         if (info->shared)
            info->flags |= DF_STATIC_TLS;
          goto dotlstoc;
 
@@ -5613,8 +5636,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_TPREL16_HIGHESTA:
          if (info->shared)
            {
-             if (!info->executable)
-               info->flags |= DF_STATIC_TLS;
+             info->flags |= DF_STATIC_TLS;
              goto dodyn;
            }
          break;
@@ -6971,9 +6993,22 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
        {
          h->plt.plist = NULL;
          h->needs_plt = 0;
+         h->pointer_equality_needed = 0;
        }
       else if (abiversion (info->output_bfd) == 2)
        {
+         /* Taking a function's address in a read/write section
+            doesn't require us to define the function symbol in the
+            executable on a global entry stub.  A dynamic reloc can
+            be used instead.  */
+         if (h->pointer_equality_needed
+             && h->type != STT_GNU_IFUNC
+             && !readonly_dynrelocs (h))
+           {
+             h->pointer_equality_needed = 0;
+             h->non_got_ref = 0;
+           }
+
          /* After adjust_dynamic_symbol, non_got_ref set in the
             non-shared case means that we have allocated space in
             .dynbss for the symbol and thus dyn_relocs for this
@@ -6983,10 +7018,10 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
             relocations against this symbol to the PLT entry.  Allow
             dynamic relocs if the reference is weak, and the dynamic
             relocs will not cause text relocation.  */
-         if (!h->ref_regular_nonweak
-             && h->non_got_ref
-             && h->type != STT_GNU_IFUNC
-             && !readonly_dynrelocs (h))
+         else if (!h->ref_regular_nonweak
+                  && h->non_got_ref
+                  && h->type != STT_GNU_IFUNC
+                  && !readonly_dynrelocs (h))
            h->non_got_ref = 0;
 
          /* If making a plt entry, then we don't need copy relocs.  */
@@ -11859,7 +11894,8 @@ static const unsigned char glink_eh_frame_cie[] =
   65,                                  /* RA reg.  */
   1,                                   /* Augmentation size.  */
   DW_EH_PE_pcrel | DW_EH_PE_sdata4,    /* FDE encoding.  */
-  DW_CFA_def_cfa, 1, 0                 /* def_cfa: r1 offset 0.  */
+  DW_CFA_def_cfa, 1, 0,                        /* def_cfa: r1 offset 0.  */
+  0, 0, 0, 0
 };
 
 /* Stripping output sections is normally done before dynamic section
@@ -12291,7 +12327,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
               stub_sec != NULL;
               stub_sec = stub_sec->next)
            if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
-             size += 20;
+             size += 24;
          if (htab->glink != NULL && htab->glink->size != 0)
            size += 24;
          if (size != 0)
@@ -12331,6 +12367,89 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
       (*htab->params->layout_sections_again) ();
     }
 
+  if (htab->glink_eh_frame != NULL
+      && htab->glink_eh_frame->size != 0)
+    {
+      bfd_vma val;
+      bfd_byte *p, *last_fde;
+      size_t last_fde_len, size, align, pad;
+      asection *stub_sec;
+
+      p = bfd_zalloc (htab->glink_eh_frame->owner, htab->glink_eh_frame->size);
+      if (p == NULL)
+       return FALSE;
+      htab->glink_eh_frame->contents = p;
+      last_fde = p;
+
+      memcpy (p, glink_eh_frame_cie, sizeof (glink_eh_frame_cie));
+      /* CIE length (rewrite in case little-endian).  */
+      last_fde_len = sizeof (glink_eh_frame_cie) - 4;
+      bfd_put_32 (htab->elf.dynobj, last_fde_len, p);
+      p += sizeof (glink_eh_frame_cie);
+
+      for (stub_sec = htab->params->stub_bfd->sections;
+          stub_sec != NULL;
+          stub_sec = stub_sec->next)
+       if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
+         {
+           last_fde = p;
+           last_fde_len = 20;
+           /* FDE length.  */
+           bfd_put_32 (htab->elf.dynobj, 20, p);
+           p += 4;
+           /* CIE pointer.  */
+           val = p - htab->glink_eh_frame->contents;
+           bfd_put_32 (htab->elf.dynobj, val, p);
+           p += 4;
+           /* Offset to stub section, written later.  */
+           p += 4;
+           /* stub section size.  */
+           bfd_put_32 (htab->elf.dynobj, stub_sec->size, p);
+           p += 4;
+           /* Augmentation.  */
+           p += 1;
+           /* Pad.  */
+           p += 7;
+         }
+      if (htab->glink != NULL && htab->glink->size != 0)
+       {
+         last_fde = p;
+         last_fde_len = 20;
+         /* FDE length.  */
+         bfd_put_32 (htab->elf.dynobj, 20, p);
+         p += 4;
+         /* CIE pointer.  */
+         val = p - htab->glink_eh_frame->contents;
+         bfd_put_32 (htab->elf.dynobj, val, p);
+         p += 4;
+         /* Offset to .glink, written later.  */
+         p += 4;
+         /* .glink size.  */
+         bfd_put_32 (htab->elf.dynobj, htab->glink->size - 8, p);
+         p += 4;
+         /* Augmentation.  */
+         p += 1;
+
+         *p++ = DW_CFA_advance_loc + 1;
+         *p++ = DW_CFA_register;
+         *p++ = 65;
+         *p++ = 12;
+         *p++ = DW_CFA_advance_loc + 4;
+         *p++ = DW_CFA_restore_extended;
+         *p++ = 65;
+       }
+      /* Subsume any padding into the last FDE if user .eh_frame
+        sections are aligned more than glink_eh_frame.  Otherwise any
+        zero padding will be seen as a terminator.  */
+      size = p - htab->glink_eh_frame->contents;
+      align = 1;
+      align <<= htab->glink_eh_frame->output_section->alignment_power;
+      align -= 1;
+      pad = ((size + align) & ~align) - size;
+      htab->glink_eh_frame->size = size + pad;
+      bfd_put_32 (htab->elf.dynobj, last_fde_len + pad, last_fde);
+    }
+
   maybe_strip_output (info, htab->brlt);
   if (htab->glink_eh_frame != NULL)
     maybe_strip_output (info, htab->glink_eh_frame);
@@ -12395,15 +12514,24 @@ ppc64_elf_set_toc (struct bfd_link_info *info, bfd *obfd)
 
   _bfd_set_gp_value (obfd, TOCstart);
 
-  if (info != NULL && s != NULL && is_ppc64_elf (obfd))
+  if (info != NULL && s != NULL)
     {
       struct ppc_link_hash_table *htab = ppc_hash_table (info);
 
-      if (htab != NULL
-         && htab->elf.hgot != NULL)
+      if (htab != NULL)
+       {
+         if (htab->elf.hgot != NULL)
+           {
+             htab->elf.hgot->root.u.def.value = TOC_BASE_OFF;
+             htab->elf.hgot->root.u.def.section = s;
+           }
+       }
+      else
        {
-         htab->elf.hgot->root.u.def.value = TOC_BASE_OFF;
-         htab->elf.hgot->root.u.def.section = s;
+         struct bfd_link_hash_entry *bh = NULL;
+         _bfd_generic_link_add_one_symbol (info, obfd, ".TOC.", BSF_GLOBAL,
+                                           s, TOC_BASE_OFF, NULL, FALSE,
+                                           FALSE, &bh);
        }
     }
   return TOCstart;
@@ -12460,6 +12588,32 @@ build_global_entry_stubs (struct elf_link_hash_entry *h, void *inf)
            htab->stub_error = TRUE;
          }
 
+       htab->stub_count[ppc_stub_global_entry - 1] += 1;
+       if (htab->params->emit_stub_syms)
+         {
+           size_t len = strlen (h->root.root.string);
+           char *name = bfd_malloc (sizeof "12345678.global_entry." + len);
+
+           if (name == NULL)
+             return FALSE;
+
+           sprintf (name, "%08x.global_entry.%s", s->id, h->root.root.string);
+           h = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE);
+           if (h == NULL)
+             return FALSE;
+           if (h->root.type == bfd_link_hash_new)
+             {
+               h->root.type = bfd_link_hash_defined;
+               h->root.u.def.section = s;
+               h->root.u.def.value = p - s->contents;
+               h->ref_regular = 1;
+               h->def_regular = 1;
+               h->ref_regular_nonweak = 1;
+               h->forced_local = 1;
+               h->non_elf = 0;
+             }
+         }
+
        if (PPC_HA (off) != 0)
          {
            bfd_put_32 (s->owner, ADDIS_R12_R12 | PPC_HA (off), p);
@@ -12638,7 +12792,7 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
        elf_link_hash_traverse (&htab->elf, build_global_entry_stubs, info);
     }
 
-  if (htab->brlt->size != 0)
+  if (htab->brlt != NULL && htab->brlt->size != 0)
     {
       htab->brlt->contents = bfd_zalloc (htab->brlt->owner,
                                         htab->brlt->size);
@@ -12653,117 +12807,6 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
        return FALSE;
     }
 
-  if (htab->glink_eh_frame != NULL
-      && htab->glink_eh_frame->size != 0)
-    {
-      bfd_vma val;
-      bfd_byte *last_fde;
-      size_t last_fde_len, size, align, pad;
-
-      p = bfd_zalloc (htab->glink_eh_frame->owner, htab->glink_eh_frame->size);
-      if (p == NULL)
-       return FALSE;
-      htab->glink_eh_frame->contents = p;
-      last_fde = p;
-
-      htab->glink_eh_frame->rawsize = htab->glink_eh_frame->size;
-
-      memcpy (p, glink_eh_frame_cie, sizeof (glink_eh_frame_cie));
-      /* CIE length (rewrite in case little-endian).  */
-      last_fde_len = sizeof (glink_eh_frame_cie) - 4;
-      bfd_put_32 (htab->elf.dynobj, last_fde_len, p);
-      p += sizeof (glink_eh_frame_cie);
-
-      for (stub_sec = htab->params->stub_bfd->sections;
-          stub_sec != NULL;
-          stub_sec = stub_sec->next)
-       if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
-         {
-           last_fde = p;
-           last_fde_len = 16;
-           /* FDE length.  */
-           bfd_put_32 (htab->elf.dynobj, 16, p);
-           p += 4;
-           /* CIE pointer.  */
-           val = p - htab->glink_eh_frame->contents;
-           bfd_put_32 (htab->elf.dynobj, val, p);
-           p += 4;
-           /* Offset to stub section.  */
-           val = (stub_sec->output_section->vma
-                  + stub_sec->output_offset);
-           val -= (htab->glink_eh_frame->output_section->vma
-                   + htab->glink_eh_frame->output_offset);
-           val -= p - htab->glink_eh_frame->contents;
-           if (val + 0x80000000 > 0xffffffff)
-             {
-               info->callbacks->einfo
-                 (_("%P: %s offset too large for .eh_frame sdata4 encoding"),
-                  stub_sec->name);
-               return FALSE;
-             }
-           bfd_put_32 (htab->elf.dynobj, val, p);
-           p += 4;
-           /* stub section size.  */
-           bfd_put_32 (htab->elf.dynobj, stub_sec->rawsize, p);
-           p += 4;
-           /* Augmentation.  */
-           p += 1;
-           /* Pad.  */
-           p += 3;
-         }
-      if (htab->glink != NULL && htab->glink->size != 0)
-       {
-         last_fde = p;
-         last_fde_len = 20;
-         /* FDE length.  */
-         bfd_put_32 (htab->elf.dynobj, 20, p);
-         p += 4;
-         /* CIE pointer.  */
-         val = p - htab->glink_eh_frame->contents;
-         bfd_put_32 (htab->elf.dynobj, val, p);
-         p += 4;
-         /* Offset to .glink.  */
-         val = (htab->glink->output_section->vma
-                + htab->glink->output_offset
-                + 8);
-         val -= (htab->glink_eh_frame->output_section->vma
-                 + htab->glink_eh_frame->output_offset);
-         val -= p - htab->glink_eh_frame->contents;
-         if (val + 0x80000000 > 0xffffffff)
-           {
-             info->callbacks->einfo
-               (_("%P: %s offset too large for .eh_frame sdata4 encoding"),
-                htab->glink->name);
-             return FALSE;
-           }
-         bfd_put_32 (htab->elf.dynobj, val, p);
-         p += 4;
-         /* .glink size.  */
-         bfd_put_32 (htab->elf.dynobj, htab->glink->size - 8, p);
-         p += 4;
-         /* Augmentation.  */
-         p += 1;
-
-         *p++ = DW_CFA_advance_loc + 1;
-         *p++ = DW_CFA_register;
-         *p++ = 65;
-         *p++ = 12;
-         *p++ = DW_CFA_advance_loc + 4;
-         *p++ = DW_CFA_restore_extended;
-         *p++ = 65;
-       }
-      /* Subsume any padding into the last FDE if user .eh_frame
-        sections are aligned more than glink_eh_frame.  Otherwise any
-        zero padding will be seen as a terminator.  */
-      size = p - htab->glink_eh_frame->contents;
-      align = 1;
-      align <<= htab->glink_eh_frame->output_section->alignment_power;
-      align -= 1;
-      pad = ((size + align) & ~align) - size;
-      htab->glink_eh_frame->size = size + pad;
-      bfd_put_32 (htab->elf.dynobj, last_fde_len + pad, last_fde);
-    }
-
   /* Build the stubs as directed by the stub hash table.  */
   bfd_hash_traverse (&htab->stub_hash_table, ppc_build_one_stub, info);
 
@@ -12789,6 +12832,9 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
          break;
       }
 
+  /* Note that the glink_eh_frame check here is not only testing that
+     the generated size matched the calculated size but also that
+     bfd_elf_discard_info didn't make any changes to the section.  */
   if (stub_sec != NULL
       || (htab->glink_eh_frame != NULL
          && htab->glink_eh_frame->rawsize != htab->glink_eh_frame->size))
@@ -12812,7 +12858,8 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
                         "  long branch  %lu\n"
                         "  long toc adj %lu\n"
                         "  plt call     %lu\n"
-                        "  plt call toc %lu"),
+                        "  plt call toc %lu\n"
+                        "  global entry %lu"),
               stub_sec_count,
               stub_sec_count == 1 ? "" : "s",
               htab->stub_count[ppc_stub_long_branch - 1],
@@ -12820,7 +12867,8 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
               htab->stub_count[ppc_stub_plt_branch - 1],
               htab->stub_count[ppc_stub_plt_branch_r2off - 1],
               htab->stub_count[ppc_stub_plt_call - 1],
-              htab->stub_count[ppc_stub_plt_call_r2save - 1]);
+              htab->stub_count[ppc_stub_plt_call_r2save - 1],
+              htab->stub_count[ppc_stub_global_entry - 1]);
     }
   return TRUE;
 }
@@ -13545,6 +13593,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
             .          addi 2,2,.TOC.@l
             if .TOC. is in range.  */
          if (!info->shared
+             && !info->traditional_format
              && h != NULL && &h->elf == htab->elf.hgot
              && rel + 1 < relend
              && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_REL16_LO)
@@ -15053,13 +15102,81 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
                                       NULL))
     return FALSE;
 
-
   if (htab->glink_eh_frame != NULL
-      && htab->glink_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME
-      && !_bfd_elf_write_section_eh_frame (output_bfd, info,
-                                          htab->glink_eh_frame,
-                                          htab->glink_eh_frame->contents))
-    return FALSE;
+      && htab->glink_eh_frame->size != 0)
+    {
+      bfd_vma val;
+      bfd_byte *p;
+      asection *stub_sec;
+
+      p = htab->glink_eh_frame->contents + sizeof (glink_eh_frame_cie);
+      for (stub_sec = htab->params->stub_bfd->sections;
+          stub_sec != NULL;
+          stub_sec = stub_sec->next)
+       if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
+         {
+           /* FDE length.  */
+           p += 4;
+           /* CIE pointer.  */
+           p += 4;
+           /* Offset to stub section.  */
+           val = (stub_sec->output_section->vma
+                  + stub_sec->output_offset);
+           val -= (htab->glink_eh_frame->output_section->vma
+                   + htab->glink_eh_frame->output_offset
+                   + (p - htab->glink_eh_frame->contents));
+           if (val + 0x80000000 > 0xffffffff)
+             {
+               info->callbacks->einfo
+                 (_("%P: %s offset too large for .eh_frame sdata4 encoding"),
+                  stub_sec->name);
+               return FALSE;
+             }
+           bfd_put_32 (dynobj, val, p);
+           p += 4;
+           /* stub section size.  */
+           p += 4;
+           /* Augmentation.  */
+           p += 1;
+           /* Pad.  */
+           p += 7;
+         }
+      if (htab->glink != NULL && htab->glink->size != 0)
+       {
+         /* FDE length.  */
+         p += 4;
+         /* CIE pointer.  */
+         p += 4;
+         /* Offset to .glink.  */
+         val = (htab->glink->output_section->vma
+                + htab->glink->output_offset
+                + 8);
+         val -= (htab->glink_eh_frame->output_section->vma
+                 + htab->glink_eh_frame->output_offset
+                 + (p - htab->glink_eh_frame->contents));
+         if (val + 0x80000000 > 0xffffffff)
+           {
+             info->callbacks->einfo
+               (_("%P: %s offset too large for .eh_frame sdata4 encoding"),
+                htab->glink->name);
+             return FALSE;
+           }
+         bfd_put_32 (dynobj, val, p);
+         p += 4;
+         /* .glink size.  */
+         p += 4;
+         /* Augmentation.  */
+         p += 1;
+         /* Ops.  */
+         p += 7;
+       }
+
+      if (htab->glink_eh_frame->sec_info_type == SEC_INFO_TYPE_EH_FRAME
+         && !_bfd_elf_write_section_eh_frame (output_bfd, info,
+                                              htab->glink_eh_frame,
+                                              htab->glink_eh_frame->contents))
+       return FALSE;
+    }
 
   /* We need to handle writing out multiple GOT sections ourselves,
      since we didn't add them to DYNOBJ.  We know dynobj is the first
This page took 0.033331 seconds and 4 git commands to generate.