- BFD_ASSERT (sgot != NULL);
-
- if (h != NULL)
- {
- bfd_vma off = h->got.offset;
- BFD_ASSERT (off != (bfd_vma) -1);
-
- if (! elf_hash_table (info)->dynamic_sections_created
- || (info->shared
- && (info->symbolic || h->dynindx == -1)
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
- {
- /* This is actually a static link, or it is a -Bsymbolic
- link and the symbol is defined locally, or the symbol
- was forced to be local because of a version file. We
- must initialize this entry in the global offset table.
- Since the offset must always be a multiple of 8, we
- use the least significant bit to record whether we
- have initialized it already.
-
- When doing a dynamic link, we create a .rela.got
- relocation entry to initialize the value. This is
- done in the finish_dynamic_symbol routine. */
- if ((off & 1) != 0)
- off &= ~1;
- else
- {
- bfd_put_64 (output_bfd, relocation,
- sgot->contents + off);
- h->got.offset |= 1;
- }
- }
- relocation = sgot->output_offset + off;
- }
- else
- {
- bfd_vma off;
-
- BFD_ASSERT (local_got_offsets != NULL
- && local_got_offsets[r_symndx] != (bfd_vma) -1);
-
- off = local_got_offsets[r_symndx];
-
- /* The offset must always be a multiple of 8. We use
- the least significant bit to record whether we have
- already generated the necessary reloc. */
- if ((off & 1) != 0)
- off &= ~1;
- else
- {
- bfd_put_64 (output_bfd, relocation, sgot->contents + off);
-
- if (info->shared)
- {
- asection *srelgot;
- Elf_Internal_Rela outrel;
-
- /* We need to generate a R_X86_64_RELATIVE reloc
- for the dynamic linker. */
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
- BFD_ASSERT (srelgot != NULL);
-
- outrel.r_offset = (sgot->output_section->vma
- + sgot->output_offset
- + off);
- outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE);
- outrel.r_addend = relocation;
- bfd_elf64_swap_reloca_out (output_bfd, &outrel,
- (((Elf64_External_Rela *)
- srelgot->contents)
- + srelgot->reloc_count));
- ++srelgot->reloc_count;
- }
-
- local_got_offsets[r_symndx] |= 1;
- }
-
- relocation = sgot->output_offset + off;
- }
-
- break;
-