OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [elf64-x86-64.c] - Diff between revs 161 and 163

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 161 Rev 163
Line 696... Line 696...
     yet.  */
     yet.  */
  bfd_vma tlsdesc_plt;
  bfd_vma tlsdesc_plt;
  /* The offset into sgot of the GOT entry used by the PLT entry
  /* The offset into sgot of the GOT entry used by the PLT entry
     above.  */
     above.  */
  bfd_vma tlsdesc_got;
  bfd_vma tlsdesc_got;
 
 
 
  /* The index of the next R_X86_64_JUMP_SLOT entry in .rela.plt.  */
 
  bfd_vma next_jump_slot_index;
 
  /* The index of the next R_X86_64_IRELATIVE entry in .rela.plt.  */
 
  bfd_vma next_irelative_index;
};
};
 
 
/* Get the x86-64 ELF linker hash table from a link_info structure.  */
/* Get the x86-64 ELF linker hash table from a link_info structure.  */
 
 
#define elf_x86_64_hash_table(p) \
#define elf_x86_64_hash_table(p) \
Line 837... Line 842...
  ret->tlsdesc_plt = 0;
  ret->tlsdesc_plt = 0;
  ret->tlsdesc_got = 0;
  ret->tlsdesc_got = 0;
  ret->tls_ld_got.refcount = 0;
  ret->tls_ld_got.refcount = 0;
  ret->sgotplt_jump_table_size = 0;
  ret->sgotplt_jump_table_size = 0;
  ret->tls_module_base = NULL;
  ret->tls_module_base = NULL;
 
  ret->next_jump_slot_index = 0;
 
  ret->next_irelative_index = 0;
 
 
  if (ABI_64_P (abfd))
  if (ABI_64_P (abfd))
    {
    {
      ret->r_info = elf64_r_info;
      ret->r_info = elf64_r_info;
      ret->r_sym = elf64_r_sym;
      ret->r_sym = elf64_r_sym;
Line 1005... Line 1012...
  /* Set the right machine number for an x86-64 elf64 file.  */
  /* Set the right machine number for an x86-64 elf64 file.  */
  bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x86_64);
  bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x86_64);
  return TRUE;
  return TRUE;
}
}
 
 
typedef union
 
  {
 
    unsigned char c[2];
 
    uint16_t i;
 
  }
 
x86_64_opcode16;
 
 
 
typedef union
 
  {
 
    unsigned char c[4];
 
    uint32_t i;
 
  }
 
x86_64_opcode32;
 
 
 
/* Return TRUE if the TLS access code sequence support transition
/* Return TRUE if the TLS access code sequence support transition
   from R_TYPE.  */
   from R_TYPE.  */
 
 
static bfd_boolean
static bfd_boolean
elf_x86_64_check_tls_transition (bfd *abfd,
elf_x86_64_check_tls_transition (bfd *abfd,
Line 1074... Line 1067...
             can transit to different access model.  For 32bit, only
             can transit to different access model.  For 32bit, only
                leaq foo@tlsgd(%rip), %rdi
                leaq foo@tlsgd(%rip), %rdi
                .word 0x6666; rex64; call __tls_get_addr
                .word 0x6666; rex64; call __tls_get_addr
             can transit to different access model.  */
             can transit to different access model.  */
 
 
          static x86_64_opcode32 call = { { 0x66, 0x66, 0x48, 0xe8 } };
          static const unsigned char call[] = { 0x66, 0x66, 0x48, 0xe8 };
 
          static const unsigned char leaq[] = { 0x66, 0x48, 0x8d, 0x3d };
 
 
          if ((offset + 12) > sec->size
          if ((offset + 12) > sec->size
              || bfd_get_32 (abfd, contents + offset + 4) != call.i)
              || memcmp (contents + offset + 4, call, 4) != 0)
            return FALSE;
            return FALSE;
 
 
          if (ABI_64_P (abfd))
          if (ABI_64_P (abfd))
            {
            {
              static x86_64_opcode32 leaq = { { 0x66, 0x48, 0x8d, 0x3d } };
 
              if (offset < 4
              if (offset < 4
                  || bfd_get_32 (abfd, contents + offset - 4) != leaq.i)
                  || memcmp (contents + offset - 4, leaq, 4) != 0)
                return FALSE;
                return FALSE;
            }
            }
          else
          else
            {
            {
              static x86_64_opcode16 lea = { { 0x8d, 0x3d } };
 
              if (offset < 3
              if (offset < 3
                  || bfd_get_8 (abfd, contents + offset - 3) != 0x48
                  || memcmp (contents + offset - 3, leaq + 1, 3) != 0)
                  || bfd_get_16 (abfd, contents + offset - 2) != lea.i)
 
                return FALSE;
                return FALSE;
            }
            }
        }
        }
      else
      else
        {
        {
          /* Check transition from LD access model.  Only
          /* Check transition from LD access model.  Only
                leaq foo@tlsld(%rip), %rdi;
                leaq foo@tlsld(%rip), %rdi;
                call __tls_get_addr
                call __tls_get_addr
             can transit to different access model.  */
             can transit to different access model.  */
 
 
          static x86_64_opcode32 ld = { { 0x48, 0x8d, 0x3d, 0xe8 } };
          static const unsigned char lea[] = { 0x48, 0x8d, 0x3d };
          x86_64_opcode32 op;
 
 
 
          if (offset < 3 || (offset + 9) > sec->size)
          if (offset < 3 || (offset + 9) > sec->size)
            return FALSE;
            return FALSE;
 
 
          op.i = bfd_get_32 (abfd, contents + offset - 3);
          if (memcmp (contents + offset - 3, lea, 3) != 0
          op.c[3] = bfd_get_8 (abfd, contents + offset + 4);
              || 0xe8 != *(contents + offset + 4))
          if (op.i != ld.i)
 
            return FALSE;
            return FALSE;
        }
        }
 
 
      r_symndx = htab->r_sym (rel[1].r_info);
      r_symndx = htab->r_sym (rel[1].r_info);
      if (r_symndx < symtab_hdr->sh_info)
      if (r_symndx < symtab_hdr->sh_info)
Line 1189... Line 1179...
                call *x@tlsdesc(%rax)
                call *x@tlsdesc(%rax)
       */
       */
      if (offset + 2 <= sec->size)
      if (offset + 2 <= sec->size)
        {
        {
          /* Make sure that it's a call *x@tlsdesc(%rax).  */
          /* Make sure that it's a call *x@tlsdesc(%rax).  */
          static x86_64_opcode16 call = { { 0xff, 0x10 } };
          static const unsigned char call[] = { 0xff, 0x10 };
          return bfd_get_16 (abfd, contents + offset) == call.i;
          return memcmp (contents + offset, call, 2) == 0;
        }
        }
 
 
      return FALSE;
      return FALSE;
 
 
    default:
    default:
Line 2682... Line 2672...
 
 
  /* For every jump slot reserved in the sgotplt, reloc_count is
  /* For every jump slot reserved in the sgotplt, reloc_count is
     incremented.  However, when we reserve space for TLS descriptors,
     incremented.  However, when we reserve space for TLS descriptors,
     it's not incremented, so in order to compute the space reserved
     it's not incremented, so in order to compute the space reserved
     for them, it suffices to multiply the reloc count by the jump
     for them, it suffices to multiply the reloc count by the jump
     slot size.  */
     slot size.
 
 
 
     PR ld/13302: We start next_irelative_index at the end of .rela.plt
 
     so that R_X86_64_IRELATIVE entries come last.  */
  if (htab->elf.srelplt)
  if (htab->elf.srelplt)
 
    {
    htab->sgotplt_jump_table_size
    htab->sgotplt_jump_table_size
      = elf_x86_64_compute_jump_table_size (htab);
      = elf_x86_64_compute_jump_table_size (htab);
 
      htab->next_irelative_index = htab->elf.srelplt->reloc_count - 1;
 
    }
 
  else if (htab->elf.irelplt)
 
    htab->next_irelative_index = htab->elf.irelplt->reloc_count - 1;
 
 
  if (htab->tlsdesc_plt)
  if (htab->tlsdesc_plt)
    {
    {
      /* If we're not using lazy TLS relocations, don't generate the
      /* If we're not using lazy TLS relocations, don't generate the
         PLT and GOT entries they require.  */
         PLT and GOT entries they require.  */
Line 3156... Line 3154...
                  bfd_set_error (bfd_error_bad_value);
                  bfd_set_error (bfd_error_bad_value);
                  return FALSE;
                  return FALSE;
                }
                }
 
 
              /* Generate dynamic relcoation only when there is a
              /* Generate dynamic relcoation only when there is a
                 non-GOF reference in a shared object.  */
                 non-GOT reference in a shared object.  */
              if (info->shared && h->non_got_ref)
              if (info->shared && h->non_got_ref)
                {
                {
                  Elf_Internal_Rela outrel;
                  Elf_Internal_Rela outrel;
                  asection *sreloc;
                  asection *sreloc;
 
                  bfd_boolean relocate;
 
 
                  /* Need a dynamic relocation to get the real function
                  /* Need a dynamic relocation to get the real function
                     address.  */
                     address.  */
                  outrel.r_offset = _bfd_elf_section_offset (output_bfd,
                  outrel.r_offset = _bfd_elf_section_offset (output_bfd,
                                                             info,
                                                             info,
Line 3180... Line 3179...
                  if (h->dynindx == -1
                  if (h->dynindx == -1
                      || h->forced_local
                      || h->forced_local
                      || info->executable)
                      || info->executable)
                    {
                    {
                      /* This symbol is resolved locally.  */
                      /* This symbol is resolved locally.  */
                      outrel.r_info = htab->r_info (0, R_X86_64_IRELATIVE);
                      outrel.r_info = htab->r_info (0, R_X86_64_RELATIVE);
                      outrel.r_addend = (h->root.u.def.value
                      outrel.r_addend = relocation;
                                         + h->root.u.def.section->output_section->vma
                      relocate = FALSE;
                                         + h->root.u.def.section->output_offset);
 
                    }
                    }
                  else
                  else
                    {
                    {
                      outrel.r_info = htab->r_info (h->dynindx, r_type);
                      outrel.r_info = htab->r_info (h->dynindx, r_type);
                      outrel.r_addend = 0;
                      outrel.r_addend = 0;
 
                      relocate = FALSE;
                    }
                    }
 
 
                  sreloc = htab->elf.irelifunc;
                  sreloc = htab->elf.irelifunc;
                  elf_append_rela (output_bfd, sreloc, &outrel);
                  elf_append_rela (output_bfd, sreloc, &outrel);
 
 
                  /* If this reloc is against an external symbol, we
                  /* If this reloc is against an external symbol, we
                     do not want to fiddle with the addend.  Otherwise,
                     do not want to fiddle with the addend.  Otherwise,
                     we need to include the symbol value so that it
                     we need to include the symbol value so that it
                     becomes an addend for the dynamic reloc.  For an
                     becomes an addend for the dynamic reloc.  For an
                     internal symbol, we have updated addend.  */
                     internal symbol, we have updated addend.  */
 
                  if (! relocate)
                  continue;
                  continue;
                }
                }
              /* FALLTHROUGH */
              /* FALLTHROUGH */
            case R_X86_64_PC32:
            case R_X86_64_PC32:
            case R_X86_64_PC64:
            case R_X86_64_PC64:
Line 4101... Line 4101...
      /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
      /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
         because such sections are not SEC_ALLOC and thus ld.so will
         because such sections are not SEC_ALLOC and thus ld.so will
         not process them.  */
         not process them.  */
      if (unresolved_reloc
      if (unresolved_reloc
          && !((input_section->flags & SEC_DEBUGGING) != 0
          && !((input_section->flags & SEC_DEBUGGING) != 0
               && h->def_dynamic))
               && h->def_dynamic)
 
          && _bfd_elf_section_offset (output_bfd, info, input_section,
 
                                      rel->r_offset) != (bfd_vma) -1)
        (*_bfd_error_handler)
        (*_bfd_error_handler)
          (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
          (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
           input_bfd,
           input_bfd,
           input_section,
           input_section,
           (long) rel->r_offset,
           (long) rel->r_offset,
Line 4218... Line 4220...
 
 
         For static executables, we don't reserve anything.  */
         For static executables, we don't reserve anything.  */
 
 
      if (plt == htab->elf.splt)
      if (plt == htab->elf.splt)
        {
        {
          plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;
          got_offset = h->plt.offset / PLT_ENTRY_SIZE - 1;
          got_offset = (plt_index + 3) * GOT_ENTRY_SIZE;
          got_offset = (got_offset + 3) * GOT_ENTRY_SIZE;
        }
        }
      else
      else
        {
        {
          plt_index = h->plt.offset / PLT_ENTRY_SIZE;
          got_offset = h->plt.offset / PLT_ENTRY_SIZE;
          got_offset = plt_index * GOT_ENTRY_SIZE;
          got_offset = got_offset * GOT_ENTRY_SIZE;
        }
        }
 
 
      /* Fill in the entry in the procedure linkage table.  */
      /* Fill in the entry in the procedure linkage table.  */
      memcpy (plt->contents + h->plt.offset, elf_x86_64_plt_entry,
      memcpy (plt->contents + h->plt.offset, elf_x86_64_plt_entry,
              PLT_ENTRY_SIZE);
              PLT_ENTRY_SIZE);
Line 4246... Line 4248...
                       - plt->output_offset
                       - plt->output_offset
                       - h->plt.offset
                       - h->plt.offset
                       - 6),
                       - 6),
                  plt->contents + h->plt.offset + 2);
                  plt->contents + h->plt.offset + 2);
 
 
      /* Don't fill PLT entry for static executables.  */
 
      if (plt == htab->elf.splt)
 
        {
 
          /* Put relocation index.  */
 
          bfd_put_32 (output_bfd, plt_index,
 
                      plt->contents + h->plt.offset + 7);
 
          /* Put offset for jmp .PLT0.  */
 
          bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE),
 
                      plt->contents + h->plt.offset + 12);
 
        }
 
 
 
      /* Fill in the entry in the global offset table, initially this
      /* Fill in the entry in the global offset table, initially this
         points to the pushq instruction in the PLT which is at offset 6.  */
         points to the pushq instruction in the PLT which is at offset 6.  */
      bfd_put_64 (output_bfd, (plt->output_section->vma
      bfd_put_64 (output_bfd, (plt->output_section->vma
                               + plt->output_offset
                               + plt->output_offset
                               + h->plt.offset + 6),
                               + h->plt.offset + 6),
Line 4280... Line 4271...
             R_X86_64_IRELATIVE instead of R_X86_64_JUMP_SLOT.  */
             R_X86_64_IRELATIVE instead of R_X86_64_JUMP_SLOT.  */
          rela.r_info = htab->r_info (0, R_X86_64_IRELATIVE);
          rela.r_info = htab->r_info (0, R_X86_64_IRELATIVE);
          rela.r_addend = (h->root.u.def.value
          rela.r_addend = (h->root.u.def.value
                           + h->root.u.def.section->output_section->vma
                           + h->root.u.def.section->output_section->vma
                           + h->root.u.def.section->output_offset);
                           + h->root.u.def.section->output_offset);
 
          /* R_X86_64_IRELATIVE comes last.  */
 
          plt_index = htab->next_irelative_index--;
        }
        }
      else
      else
        {
        {
          rela.r_info = htab->r_info (h->dynindx, R_X86_64_JUMP_SLOT);
          rela.r_info = htab->r_info (h->dynindx, R_X86_64_JUMP_SLOT);
          rela.r_addend = 0;
          rela.r_addend = 0;
 
          plt_index = htab->next_jump_slot_index++;
 
        }
 
 
 
      /* Don't fill PLT entry for static executables.  */
 
      if (plt == htab->elf.splt)
 
        {
 
          /* Put relocation index.  */
 
          bfd_put_32 (output_bfd, plt_index,
 
                      plt->contents + h->plt.offset + 7);
 
          /* Put offset for jmp .PLT0.  */
 
          bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE),
 
                      plt->contents + h->plt.offset + 12);
        }
        }
 
 
      bed = get_elf_backend_data (output_bfd);
      bed = get_elf_backend_data (output_bfd);
      loc = relplt->contents + plt_index * bed->s->sizeof_rela;
      loc = relplt->contents + plt_index * bed->s->sizeof_rela;
      bed->s->swap_reloca_out (output_bfd, &rela, loc);
      bed->s->swap_reloca_out (output_bfd, &rela, loc);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.