2009-06-06 H.J. Lu <hongjiu.lu@intel.com>
authorH.J. Lu <hjl.tools@gmail.com>
Sat, 6 Jun 2009 11:48:11 +0000 (11:48 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Sat, 6 Jun 2009 11:48:11 +0000 (11:48 +0000)
* elf32-i386.c (elf_i386_check_relocs): Make room for dynamic
relocation for R_386_32 against STT_GNU_IFUNC symbol when
building shared object.  Check info->executable instead of
!info->shared when setting non_got_ref.
(elf_i386_allocate_dynrelocs): Allocate dynamic relocation
for non-GOT reference of STT_GNU_IFUNC symbol in shared
object. Allocate GOT relocation agsinst STT_GNU_IFUNC
symbol if needed.
(elf_i386_relocate_section): Output dynamic relocation for
R_386_32 against STT_GNU_IFUNC symbol to get the real
function address when building shared object.
(elf_i386_finish_dynamic_symbol): Output R_386_GLOB_DAT
relocation for STT_GNU_IFUNC symbol in shared object.

* elf64-x86-64.c (elf64_x86_64_check_relocs): Make room for
dynamic relocation for R_X86_64_64 against STT_GNU_IFUNC
symbol when building shared object.  Check info->executable
instead of !info->shared when setting non_got_ref.
(elf64_x86_64_allocate_dynrelocs): Allocate dynamic relocation
for non-GOT reference of STT_GNU_IFUNC symbol in shared
library. Allocate GOT relocation agsinst STT_GNU_IFUNC symbol
if needed.
(elf64_x86_64_relocate_section): Output dynamic relocation
for R_X86_64_64 against STT_GNU_IFUNC symbol to get the real
function address when building shared object.
(elf64_x86_64_finish_dynamic_symbol): Output R_X86_64_GLOB_DAT
relocation for STT_GNU_IFUNC symbol in shared object.

bfd/ChangeLog
bfd/elf32-i386.c
bfd/elf64-x86-64.c

index 439e296723725b2145554af12f42dc61cd5634f7..894897377bf8c758d6d43f173092271d14059f5f 100644 (file)
@@ -1,3 +1,33 @@
+2009-06-06  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * elf32-i386.c (elf_i386_check_relocs): Make room for dynamic
+       relocation for R_386_32 against STT_GNU_IFUNC symbol when
+       building shared object.  Check info->executable instead of
+       !info->shared when setting non_got_ref.
+       (elf_i386_allocate_dynrelocs): Allocate dynamic relocation
+       for non-GOT reference of STT_GNU_IFUNC symbol in shared
+       object. Allocate GOT relocation agsinst STT_GNU_IFUNC
+       symbol if needed.
+       (elf_i386_relocate_section): Output dynamic relocation for
+       R_386_32 against STT_GNU_IFUNC symbol to get the real
+       function address when building shared object.
+       (elf_i386_finish_dynamic_symbol): Output R_386_GLOB_DAT
+       relocation for STT_GNU_IFUNC symbol in shared object.
+
+       * elf64-x86-64.c (elf64_x86_64_check_relocs): Make room for
+       dynamic relocation for R_X86_64_64 against STT_GNU_IFUNC
+       symbol when building shared object.  Check info->executable
+       instead of !info->shared when setting non_got_ref.
+       (elf64_x86_64_allocate_dynrelocs): Allocate dynamic relocation
+       for non-GOT reference of STT_GNU_IFUNC symbol in shared
+       library. Allocate GOT relocation agsinst STT_GNU_IFUNC symbol
+       if needed.
+       (elf64_x86_64_relocate_section): Output dynamic relocation
+       for R_X86_64_64 against STT_GNU_IFUNC symbol to get the real
+       function address when building shared object.
+       (elf64_x86_64_finish_dynamic_symbol): Output R_X86_64_GLOB_DAT
+       relocation for STT_GNU_IFUNC symbol in shared object.
+
 2009-06-06  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        * Makefile.am: Run "make dep-am".
index 05aada1a3f0a37b03897053572406581911d102a..8fb8742e2139c18e39528494af76a5704a06500e 100644 (file)
@@ -1325,10 +1325,48 @@ elf_i386_check_relocs (bfd *abfd,
                   return FALSE;
 
                case R_386_32:
+                 h->non_got_ref = 1;
+                 h->pointer_equality_needed = 1;
+                 if (info->shared)
+                   {
+                     struct elf_i386_dyn_relocs *p;
+                     struct elf_i386_dyn_relocs **head;
+
+                     /* We must copy these reloc types into the
+                        output file.  Create a reloc section in
+                        dynobj and make room for this reloc.  */
+                     if (sreloc == NULL)
+                       {
+                         if (htab->elf.dynobj == NULL)
+                           htab->elf.dynobj = abfd;
+
+                         sreloc = _bfd_elf_make_dynamic_reloc_section
+                           (sec, htab->elf.dynobj, 2, abfd, FALSE);
+
+                         if (sreloc == NULL)
+                           return FALSE;
+                       }
+
+                     head = &((struct elf_i386_link_hash_entry *) h)->dyn_relocs;
+                     p = *head;
+                     if (p == NULL || p->sec != sec)
+                       {
+                         bfd_size_type amt = sizeof *p;
+                         p = bfd_alloc (htab->elf.dynobj, amt);
+                         if (p == NULL)
+                           return FALSE;
+                         p->next = *head;
+                         *head = p;
+                         p->sec = sec;
+                         p->count = 0;
+                         p->pc_count = 0;
+                       }
+                     p->count += 1;
+                   }
+                 break;
+
                case R_386_PC32:
                  h->non_got_ref = 1;
-                 if (r_type != R_386_PC32)
-                   h->pointer_equality_needed = 1;
                  break;
 
                case R_386_PLT32:
@@ -1501,7 +1539,7 @@ elf_i386_check_relocs (bfd *abfd,
 
        case R_386_32:
        case R_386_PC32:
-         if (h != NULL && !info->shared)
+         if (h != NULL && info->executable)
            {
              /* If this reloc is in a read-only section, we might
                 need a copy reloc.  We can't check reliably at this
@@ -1957,7 +1995,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
       /* When building a static executable, use .iplt, .igot.plt and
         .rel.iplt sections for STT_GNU_IFUNC symbols.  */
-      if (htab->splt != 0)
+      if (htab->splt != NULL)
        {
          plt = htab->splt;
          gotplt = htab->sgotplt;
@@ -1992,34 +2030,50 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       relplt->size += sizeof (Elf32_External_Rel);
       relplt->reloc_count++;
 
-      /* No need for dynamic relocation for local STT_GNU_IFUNC symbol.
-        Discard space for relocations against it.  */
-      if (h->dynindx == -1 || h->forced_local)
+      /* We need dynamic relocation for STT_GNU_IFUNC symbol only
+        when there is a non-GOT reference in a shared object.  */
+      if (!info->shared
+         || !h->non_got_ref)
        eh->dyn_relocs = NULL;
 
-      /* STT_GNU_IFUNC symbol uses .got.plt, not .got.  But for
-        shared library, we must go through GOT and we can't
-        use R_386_IRELATIVE unless it is forced local.   */
-      if (info->executable
-         || info->symbolic
-         || h->forced_local)
+      /* Finally, allocate space.  */
+      for (p = eh->dyn_relocs; p != NULL; p = p->next)
        {
-         if (h->pointer_equality_needed
-             && htab->sgot != NULL)
-           {
-             /* We can't use .got.plt, which contains the real
-                function addres, since we need pointer equality.
-                We will load the GOT entry with the PLT entry
-                in elf_i386_finish_dynamic_symbol and don't
-                need GOT relocation.  */
-             h->got.offset = htab->sgot->size;
-             htab->sgot->size += 4;
-             eh->tlsdesc_got = (bfd_vma) -1;
-             goto skip_relgot;
-           }
-         else
-           h->got.refcount = 0;
+         asection * sreloc = elf_section_data (p->sec)->sreloc;
+         sreloc->size += p->count * sizeof (Elf32_External_Rel);
+       }
+
+      /* For STT_GNU_IFUNC symbol, .got.plt has the real function
+        addres and .got has the PLT entry adddress.  We will load
+        the GOT entry with the PLT entry in finish_dynamic_symbol if
+        it is used.  For branch, it uses .got.plt.  For symbol value,
+        1. Use .got.plt in a shared object if it is forced local or
+        not dynamic.
+        2. Use .got.plt in a non-shared object if pointer equality 
+        isn't needed.
+        3. Use .got.plt if .got isn't used.
+        4. Otherwise use .got so that it can be shared among different
+        objects at run-time.
+        We only need to relocate .got entry in shared object.  */
+      if ((info->shared
+          && (h->dynindx == -1
+              || h->forced_local))
+         || (!info->shared
+             && !h->pointer_equality_needed)
+         || htab->sgot == NULL)
+       {
+         /* Use .got.plt.  */
+         h->got.offset = (bfd_vma) -1;
        }
+      else
+       {
+         h->got.offset = htab->sgot->size;
+         htab->sgot->size += 4;
+         if (info->shared)
+           htab->srelgot->size += sizeof (Elf32_External_Rel);
+       }
+
+      return TRUE;
     }
   else if (htab->elf.dynamic_sections_created
           && h->plt.refcount > 0)
@@ -2166,7 +2220,6 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   else
     h->got.offset = (bfd_vma) -1;
 
-skip_relgot:
   if (eh->dyn_relocs == NULL)
     return TRUE;
 
@@ -2920,6 +2973,57 @@ elf_i386_relocate_section (bfd *output_bfd,
              return FALSE;
 
            case R_386_32:
+             /* Generate dynamic relcoation only when there is a
+                non-GOF reference in a shared object.  */
+             if (info->shared && h->non_got_ref)
+               {
+                 Elf_Internal_Rela outrel;
+                 bfd_byte *loc;
+                 asection *sreloc;
+                 bfd_vma offset;
+
+                 /* Need a dynamic relocation get the the real
+                    function adddress.  */
+                 offset = _bfd_elf_section_offset (output_bfd,
+                                                   info,
+                                                   input_section,
+                                                   rel->r_offset);
+                 if (offset == (bfd_vma) -1
+                     || offset == (bfd_vma) -2)
+                   abort ();
+
+                 outrel.r_offset = (input_section->output_section->vma
+                                    + input_section->output_offset
+                                    + offset);
+
+                 if (h->dynindx == -1
+                     || h->forced_local)
+                   {
+                     /* This symbol is resolved locally.  */
+                     outrel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
+                     bfd_put_32 (output_bfd,
+                                 (h->root.u.def.value 
+                                  + h->root.u.def.section->output_section->vma
+                                  + h->root.u.def.section->output_offset),
+                                 contents + offset);
+                   }
+                 else
+                   outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
+
+                 sreloc = elf_section_data (input_section)->sreloc;
+                 loc = sreloc->contents;
+                 loc += (sreloc->reloc_count++
+                         * sizeof (Elf32_External_Rel));
+                 bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
+
+                 /* If this reloc is against an external symbol, we
+                    do not want to fiddle with the addend.  Otherwise,
+                    we need to include the symbol value so that it
+                    becomes an addend for the dynamic reloc.  For an
+                    internal symbol, we have updated addend.  */
+                 continue;
+               }
+
            case R_386_PC32:
            case R_386_PLT32:
              goto do_relocation;
@@ -3950,7 +4054,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
 
       /* When building a static executable, use .iplt, .igot.plt and
         .rel.iplt sections for STT_GNU_IFUNC symbols.  */
-      if (htab->splt != 0)
+      if (htab->splt != NULL)
        {
          plt = htab->splt;
          gotplt = htab->sgotplt;
@@ -4132,25 +4236,29 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
         of a version file, we just want to emit a RELATIVE reloc.
         The entry in the global offset table will already have been
         initialized in the relocate_section function.  */
-      if ((info->executable
-          || info->symbolic
-          || h->forced_local)
-         && h->def_regular
-         && h->pointer_equality_needed
+      if (h->def_regular
          && h->type == STT_GNU_IFUNC)
        {
-         /* The STT_GNU_IFUNC symbol is locally defined.  But we can't
-            use .got.plt, which contains the real function addres,
-            since we need pointer equality.  We load the GOT entry
-            with the PLT entry without relocation.  */
-         asection *plt = htab->splt ? htab->splt : htab->iplt;
-         if (htab->sgot == NULL
-             || h->plt.offset == (bfd_vma) -1)
-           abort ();
-         bfd_put_32 (output_bfd, (plt->output_section->vma
-                                  + plt->output_offset + h->plt.offset),
-                     htab->sgot->contents + h->got.offset);
-         return TRUE;
+         if (info->shared)
+           {
+             /* Generate R_386_GLOB_DAT.  */
+             goto do_glob_dat;
+           }
+         else
+           {
+             if (!h->pointer_equality_needed)
+               abort ();
+
+             /* For non-shared object, we can't use .got.plt, which
+                contains the real function addres if we need pointer
+                equality.  We load the GOT entry with the PLT entry.  */
+             asection *plt = htab->splt ? htab->splt : htab->iplt;
+             bfd_put_32 (output_bfd,
+                         (plt->output_section->vma
+                          + plt->output_offset + h->plt.offset),
+                         htab->sgot->contents + h->got.offset);
+             return TRUE;
+           }
        }
       else if (info->shared
               && SYMBOL_REFERENCES_LOCAL (info, h))
@@ -4161,6 +4269,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
       else
        {
          BFD_ASSERT((h->got.offset & 1) == 0);
+do_glob_dat:
          bfd_put_32 (output_bfd, (bfd_vma) 0,
                      htab->sgot->contents + h->got.offset);
          rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT);
index 041e28519e83e2a567e4e854de0a31308181e628..0ba575901536e93ff252acdf8c726e76bcf61a50 100644 (file)
@@ -1110,9 +1110,51 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
                   bfd_set_error (bfd_error_bad_value);
                   return FALSE;
 
+               case R_X86_64_64:
+                 h->non_got_ref = 1;
+                 h->pointer_equality_needed = 1;
+                 if (info->shared)
+                   {
+                     struct elf64_x86_64_dyn_relocs *p;
+                     struct elf64_x86_64_dyn_relocs **head;
+
+                     /* We must copy these reloc types into the output
+                        file.  Create a reloc section in dynobj and
+                        make room for this reloc.  */
+                     if (sreloc == NULL)
+                       {
+                         if (htab->elf.dynobj == NULL)
+                           htab->elf.dynobj = abfd;
+
+                         sreloc = _bfd_elf_make_dynamic_reloc_section
+                           (sec, htab->elf.dynobj, 3, abfd, TRUE);
+
+                         if (sreloc == NULL)
+                           return FALSE;
+                       }
+                     
+                     head = &((struct elf64_x86_64_link_hash_entry *) h)->dyn_relocs;
+                     p = *head;
+                     if (p == NULL || p->sec != sec)
+                       {
+                         bfd_size_type amt = sizeof *p;
+
+                         p = ((struct elf64_x86_64_dyn_relocs *)
+                              bfd_alloc (htab->elf.dynobj, amt));
+                         if (p == NULL)
+                           return FALSE;
+                         p->next = *head;
+                         *head = p;
+                         p->sec = sec;
+                         p->count = 0;
+                         p->pc_count = 0;
+                       }
+                     p->count += 1;
+                   }
+                 break;
+
                case R_X86_64_32S:
                case R_X86_64_32:
-               case R_X86_64_64:
                case R_X86_64_PC32:
                case R_X86_64_PC64:
                  h->non_got_ref = 1;
@@ -1329,7 +1371,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_X86_64_PC32:
        case R_X86_64_PC64:
        case R_X86_64_64:
-         if (h != NULL && !info->shared)
+         if (h != NULL && info->executable)
            {
              /* If this reloc is in a read-only section, we might
                 need a copy reloc.  We can't check reliably at this
@@ -1795,7 +1837,7 @@ elf64_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
 
       /* When building a static executable, use .iplt, .igot.plt and
         .rela.iplt sections for STT_GNU_IFUNC symbols.  */
-      if (htab->splt != 0)
+      if (htab->splt != NULL)
        {
          plt = htab->splt;
          gotplt = htab->sgotplt;
@@ -1830,34 +1872,50 @@ elf64_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
       relplt->size += sizeof (Elf64_External_Rela);
       relplt->reloc_count++;
 
-      /* No need for dynamic relocation for local STT_GNU_IFUNC symbol.
-        Discard space for relocations against it.  */
-      if (h->dynindx == -1 || h->forced_local)
+      /* We need dynamic relocation for STT_GNU_IFUNC symbol only
+        when there is a non-GOT reference in a shared object.  */
+      if (!info->shared
+         || !h->non_got_ref)
        eh->dyn_relocs = NULL;
 
-      /* STT_GNU_IFUNC symbol uses .got.plt, not .got.  But for
-        shared library, we must go through GOT and we can't
-        use R_X86_64_IRELATIVE unless it is forced local.   */
-      if (info->executable
-         || info->symbolic
-         || h->forced_local)
+      /* Finally, allocate space.  */
+      for (p = eh->dyn_relocs; p != NULL; p = p->next)
        {
-         if (h->pointer_equality_needed
-             && htab->sgot != NULL)
-           {
-             /* We can't use .got.plt, which contains the real
-                function addres, since we need pointer equality.
-                We will load the GOT entry with the PLT entry
-                in elf64_x86_64_finish_dynamic_symbol and don't
-                need GOT relocation.  */
-             h->got.offset = htab->sgot->size;
-             htab->sgot->size += GOT_ENTRY_SIZE;
-             eh->tlsdesc_got = (bfd_vma) -1;
-             goto skip_relgot;
-           }
-         else
-           h->got.refcount = 0;
+         asection * sreloc = elf_section_data (p->sec)->sreloc;
+         sreloc->size += p->count * sizeof (Elf64_External_Rela);
+       }
+
+      /* For STT_GNU_IFUNC symbol, .got.plt has the real function
+        addres and .got has the PLT entry adddress.  We will load
+        the GOT entry with the PLT entry in finish_dynamic_symbol if
+        it is used.  For branch, it uses .got.plt.  For symbol value,
+        1. Use .got.plt in a shared object if it is forced local or
+        not dynamic.
+        2. Use .got.plt in a non-shared object if pointer equality 
+        isn't needed.
+        3. Use .got.plt if .got isn't used.
+        4. Otherwise use .got so that it can be shared among different
+        objects at run-time.
+        We only need to relocate .got entry in shared object.  */
+      if ((info->shared
+          && (h->dynindx == -1
+              || h->forced_local))
+         || (!info->shared
+             && !h->pointer_equality_needed)
+         || htab->sgot == NULL)
+       {
+         /* Use .got.plt.  */
+         h->got.offset = (bfd_vma) -1;
+       }
+      else
+       {
+         h->got.offset = htab->sgot->size;
+         htab->sgot->size += GOT_ENTRY_SIZE;
+         if (info->shared)
+           htab->srelgot->size += sizeof (Elf64_External_Rela);
        }
+
+      return TRUE;
     }
   else if (htab->elf.dynamic_sections_created
           && h->plt.refcount > 0)
@@ -1984,7 +2042,6 @@ elf64_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
   else
     h->got.offset = (bfd_vma) -1;
 
-skip_relgot:
   if (eh->dyn_relocs == NULL)
     return TRUE;
 
@@ -2621,11 +2678,73 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
              return FALSE;
 
            case R_X86_64_32S:
-             if (!info->executable)
+             if (info->shared)
                abort ();
+             goto do_relocation;
+
+           case R_X86_64_64: 
+             if (rel->r_addend != 0)
+               {
+                 (*_bfd_error_handler)
+                   (_("%B: relocation %s against STT_GNU_IFUNC "
+                      "symbol `%s' has non-zero addend: %d"),
+                    input_bfd, x86_64_elf_howto_table[r_type].name,
+                    h->root.root.string, rel->r_addend);
+                 bfd_set_error (bfd_error_bad_value);
+                 return FALSE;
+               }
+
+             /* Generate dynamic relcoation only when there is a
+                non-GOF reference in a shared object.  */
+             if (info->shared && h->non_got_ref)
+               {
+                 Elf_Internal_Rela outrel;
+                 bfd_byte *loc;
+                 asection *sreloc;
+
+                 /* Need a dynamic relocation get the the real
+                    function address. */
+                 outrel.r_offset = _bfd_elf_section_offset (output_bfd,
+                                                            info,
+                                                            input_section,
+                                                            rel->r_offset);
+                 if (outrel.r_offset == (bfd_vma) -1
+                     || outrel.r_offset == (bfd_vma) -2)
+                   abort ();
+
+                 outrel.r_offset += (input_section->output_section->vma
+                                     + input_section->output_offset);
+
+                 if (h->dynindx == -1
+                     || h->forced_local)
+                   {
+                     /* This symbol is resolved locally.  */
+                     outrel.r_info = ELF64_R_INFO (0, R_X86_64_IRELATIVE);
+                     outrel.r_addend = (h->root.u.def.value
+                                        + h->root.u.def.section->output_section->vma
+                                        + h->root.u.def.section->output_offset);
+                   }
+                 else
+                   {
+                     outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
+                     outrel.r_addend = 0;
+                   }
+
+                 sreloc = elf_section_data (input_section)->sreloc;
+                 loc = sreloc->contents;
+                 loc += (sreloc->reloc_count++
+                         * sizeof (Elf64_External_Rela));
+                 bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+
+                 /* If this reloc is against an external symbol, we
+                    do not want to fiddle with the addend.  Otherwise,
+                    we need to include the symbol value so that it
+                    becomes an addend for the dynamic reloc.  For an
+                    internal symbol, we have updated addend.  */
+                 continue;
+               }
 
            case R_X86_64_32:
-           case R_X86_64_64:
            case R_X86_64_PC32:
            case R_X86_64_PC64:
            case R_X86_64_PLT32:
@@ -3596,7 +3715,7 @@ elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd,
 
       /* When building a static executable, use .iplt, .igot.plt and
         .rela.iplt sections for STT_GNU_IFUNC symbols.  */
-      if (htab->splt != 0)
+      if (htab->splt != NULL)
        {
          plt = htab->splt;
          gotplt = htab->sgotplt;
@@ -3741,25 +3860,29 @@ elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd,
         of a version file, we just want to emit a RELATIVE reloc.
         The entry in the global offset table will already have been
         initialized in the relocate_section function.  */
-      if ((info->executable
-          || info->symbolic
-          || h->forced_local)
-         && h->def_regular
-         && h->pointer_equality_needed
+      if (h->def_regular
          && h->type == STT_GNU_IFUNC)
        {
-         /* The STT_GNU_IFUNC symbol is locally defined.  But we can't
-            use .got.plt, which contains the real function addres,
-            since we need pointer equality.  We load the GOT entry
-            with the PLT entry without relocation.  */
-         asection *plt = htab->splt ? htab->splt : htab->iplt;
-         if (htab->sgot == NULL
-             || h->plt.offset == (bfd_vma) -1)
-           abort ();
-         bfd_put_64 (output_bfd, (plt->output_section->vma
-                                  + plt->output_offset + h->plt.offset),
-                     htab->sgot->contents + h->got.offset);
-         return TRUE;
+         if (info->shared)
+           {
+             /* Generate R_X86_64_GLOB_DAT.  */
+             goto do_glob_dat;
+           }
+         else
+           {
+             if (!h->pointer_equality_needed)
+               abort ();
+
+             /* For non-shared object, we can't use .got.plt, which
+                contains the real function addres if we need pointer
+                equality.  We load the GOT entry with the PLT entry.  */
+             asection *plt = htab->splt ? htab->splt : htab->iplt;
+             bfd_put_64 (output_bfd, (plt->output_section->vma
+                                      + plt->output_offset
+                                      + h->plt.offset),
+                         htab->sgot->contents + h->got.offset);
+             return TRUE;
+           }
        }
       else if (info->shared
               && SYMBOL_REFERENCES_LOCAL (info, h))
@@ -3775,6 +3898,7 @@ elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd,
       else
        {
          BFD_ASSERT((h->got.offset & 1) == 0);
+do_glob_dat:
          bfd_put_64 (output_bfd, (bfd_vma) 0,
                      htab->sgot->contents + h->got.offset);
          rela.r_info = ELF64_R_INFO (h->dynindx, R_X86_64_GLOB_DAT);
This page took 0.037068 seconds and 4 git commands to generate.