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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [bfd/] [elf32-i386.c] - Diff between revs 157 and 225

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

Rev 157 Rev 225
Line 1... Line 1...
/* Intel 80386/80486-specific support for 32-bit ELF
/* Intel 80386/80486-specific support for 32-bit ELF
   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
   2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
   2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
 
   This file is part of BFD, the Binary File Descriptor library.
   This file is part of BFD, the Binary File Descriptor library.
 
 
   This program is free software; you can redistribute it and/or modify
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
Line 24... Line 24...
#include "bfdlink.h"
#include "bfdlink.h"
#include "libbfd.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf-bfd.h"
#include "elf-vxworks.h"
#include "elf-vxworks.h"
#include "bfd_stdint.h"
#include "bfd_stdint.h"
 
#include "objalloc.h"
 
#include "hashtab.h"
 
 
/* 386 uses REL relocations instead of RELA.  */
/* 386 uses REL relocations instead of RELA.  */
#define USE_REL 1
#define USE_REL 1
 
 
#include "elf/i386.h"
#include "elf/i386.h"
Line 136... Line 138...
        bfd_elf_generic_reloc, "R_386_TLS_DESC_CALL",
        bfd_elf_generic_reloc, "R_386_TLS_DESC_CALL",
        FALSE, 0, 0, FALSE),
        FALSE, 0, 0, FALSE),
  HOWTO(R_386_TLS_DESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
  HOWTO(R_386_TLS_DESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
        bfd_elf_generic_reloc, "R_386_TLS_DESC",
        bfd_elf_generic_reloc, "R_386_TLS_DESC",
        TRUE, 0xffffffff, 0xffffffff, FALSE),
        TRUE, 0xffffffff, 0xffffffff, FALSE),
 
  HOWTO(R_386_IRELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
 
        bfd_elf_generic_reloc, "R_386_IRELATIVE",
 
        TRUE, 0xffffffff, 0xffffffff, FALSE),
 
 
  /* Another gap.  */
  /* Another gap.  */
#define R_386_tls (R_386_TLS_DESC + 1 - R_386_tls_offset)
#define R_386_irelative (R_386_IRELATIVE + 1 - R_386_tls_offset)
#define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_tls)
#define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_irelative)
 
 
/* GNU extension to record C++ vtable hierarchy.  */
/* GNU extension to record C++ vtable hierarchy.  */
  HOWTO (R_386_GNU_VTINHERIT,   /* type */
  HOWTO (R_386_GNU_VTINHERIT,   /* type */
         0,                      /* rightshift */
         0,                      /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
Line 314... Line 319...
 
 
    case BFD_RELOC_386_TLS_DESC:
    case BFD_RELOC_386_TLS_DESC:
      TRACE ("BFD_RELOC_386_TLS_DESC");
      TRACE ("BFD_RELOC_386_TLS_DESC");
      return &elf_howto_table[R_386_TLS_DESC - R_386_tls_offset];
      return &elf_howto_table[R_386_TLS_DESC - R_386_tls_offset];
 
 
 
    case BFD_RELOC_386_IRELATIVE:
 
      TRACE ("BFD_RELOC_386_IRELATIVE");
 
      return &elf_howto_table[R_386_IRELATIVE];
 
 
    case BFD_RELOC_VTABLE_INHERIT:
    case BFD_RELOC_VTABLE_INHERIT:
      TRACE ("BFD_RELOC_VTABLE_INHERIT");
      TRACE ("BFD_RELOC_VTABLE_INHERIT");
      return &elf_howto_table[R_386_GNU_VTINHERIT - R_386_vt_offset];
      return &elf_howto_table[R_386_GNU_VTINHERIT - R_386_vt_offset];
 
 
    case BFD_RELOC_VTABLE_ENTRY:
    case BFD_RELOC_VTABLE_ENTRY:
Line 353... Line 362...
 
 
  if ((indx = r_type) >= R_386_standard
  if ((indx = r_type) >= R_386_standard
      && ((indx = r_type - R_386_ext_offset) - R_386_standard
      && ((indx = r_type - R_386_ext_offset) - R_386_standard
          >= R_386_ext - R_386_standard)
          >= R_386_ext - R_386_standard)
      && ((indx = r_type - R_386_tls_offset) - R_386_ext
      && ((indx = r_type - R_386_tls_offset) - R_386_ext
          >= R_386_tls - R_386_ext)
          >= R_386_irelative - R_386_ext)
      && ((indx = r_type - R_386_vt_offset) - R_386_tls
      && ((indx = r_type - R_386_vt_offset) - R_386_irelative
          >= R_386_vt - R_386_tls))
          >= R_386_vt - R_386_irelative))
    {
    {
      (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
      (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
                             abfd, (int) r_type);
                             abfd, (int) r_type);
      indx = R_386_NONE;
      indx = R_386_NONE;
    }
    }
Line 566... Line 575...
   for the PLTResolve stub and then for each PLT entry.  */
   for the PLTResolve stub and then for each PLT entry.  */
#define PLTRESOLVE_RELOCS_SHLIB 0
#define PLTRESOLVE_RELOCS_SHLIB 0
#define PLTRESOLVE_RELOCS 2
#define PLTRESOLVE_RELOCS 2
#define PLT_NON_JUMP_SLOT_RELOCS 2
#define PLT_NON_JUMP_SLOT_RELOCS 2
 
 
/* The i386 linker needs to keep track of the number of relocs that it
 
   decides to copy as dynamic relocs in check_relocs for each symbol.
 
   This is so that it can later discard them if they are found to be
 
   unnecessary.  We store the information in a field extending the
 
   regular ELF linker hash table.  */
 
 
 
struct elf_i386_dyn_relocs
 
{
 
  struct elf_i386_dyn_relocs *next;
 
 
 
  /* The input section of the reloc.  */
 
  asection *sec;
 
 
 
  /* Total number of relocs copied for the input section.  */
 
  bfd_size_type count;
 
 
 
  /* Number of pc-relative relocs copied for the input section.  */
 
  bfd_size_type pc_count;
 
};
 
 
 
/* i386 ELF linker hash entry.  */
/* i386 ELF linker hash entry.  */
 
 
struct elf_i386_link_hash_entry
struct elf_i386_link_hash_entry
{
{
  struct elf_link_hash_entry elf;
  struct elf_link_hash_entry elf;
 
 
  /* Track dynamic relocs copied for this symbol.  */
  /* Track dynamic relocs copied for this symbol.  */
  struct elf_i386_dyn_relocs *dyn_relocs;
  struct elf_dyn_relocs *dyn_relocs;
 
 
#define GOT_UNKNOWN     0
#define GOT_UNKNOWN     0
#define GOT_NORMAL      1
#define GOT_NORMAL      1
#define GOT_TLS_GD      2
#define GOT_TLS_GD      2
#define GOT_TLS_IE      4
#define GOT_TLS_IE      4
Line 659... Line 648...
struct elf_i386_link_hash_table
struct elf_i386_link_hash_table
{
{
  struct elf_link_hash_table elf;
  struct elf_link_hash_table elf;
 
 
  /* Short-cuts to get to dynamic linker sections.  */
  /* Short-cuts to get to dynamic linker sections.  */
  asection *sgot;
 
  asection *sgotplt;
 
  asection *srelgot;
 
  asection *splt;
 
  asection *srelplt;
 
  asection *sdynbss;
  asection *sdynbss;
  asection *srelbss;
  asection *srelbss;
 
 
  /* The (unloaded but important) .rel.plt.unloaded section on VxWorks.  */
  /* The (unloaded but important) .rel.plt.unloaded section on VxWorks.  */
  asection *srelplt2;
  asection *srelplt2;
Line 688... Line 672...
 
 
  /* The amount of space used by the reserved portion of the sgotplt
  /* The amount of space used by the reserved portion of the sgotplt
     section, plus whatever space is used by the jump slots.  */
     section, plus whatever space is used by the jump slots.  */
  bfd_vma sgotplt_jump_table_size;
  bfd_vma sgotplt_jump_table_size;
 
 
  /* Small local sym to section mapping cache.  */
  /* Small local sym cache.  */
  struct sym_sec_cache sym_sec;
  struct sym_cache sym_cache;
 
 
 
  /* _TLS_MODULE_BASE_ symbol.  */
 
  struct bfd_link_hash_entry *tls_module_base;
 
 
 
  /* Used by local STT_GNU_IFUNC symbols.  */
 
  htab_t loc_hash_table;
 
  void *loc_hash_memory;
};
};
 
 
/* Get the i386 ELF linker hash table from a link_info structure.  */
/* Get the i386 ELF linker hash table from a link_info structure.  */
 
 
#define elf_i386_hash_table(p) \
#define elf_i386_hash_table(p) \
Line 703... Line 694...
  ((htab)->next_tls_desc_index * 4)
  ((htab)->next_tls_desc_index * 4)
 
 
/* Create an entry in an i386 ELF linker hash table.  */
/* Create an entry in an i386 ELF linker hash table.  */
 
 
static struct bfd_hash_entry *
static struct bfd_hash_entry *
link_hash_newfunc (struct bfd_hash_entry *entry,
elf_i386_link_hash_newfunc (struct bfd_hash_entry *entry,
                   struct bfd_hash_table *table,
                   struct bfd_hash_table *table,
                   const char *string)
                   const char *string)
{
{
  /* Allocate the structure if it has not already been allocated by a
  /* Allocate the structure if it has not already been allocated by a
     subclass.  */
     subclass.  */
  if (entry == NULL)
  if (entry == NULL)
    {
    {
      entry = bfd_hash_allocate (table,
      entry = (struct bfd_hash_entry *)
                                 sizeof (struct elf_i386_link_hash_entry));
          bfd_hash_allocate (table, sizeof (struct elf_i386_link_hash_entry));
      if (entry == NULL)
      if (entry == NULL)
        return entry;
        return entry;
    }
    }
 
 
  /* Call the allocation method of the superclass.  */
  /* Call the allocation method of the superclass.  */
Line 732... Line 723...
    }
    }
 
 
  return entry;
  return entry;
}
}
 
 
 
/* Compute a hash of a local hash entry.  We use elf_link_hash_entry
 
  for local symbol so that we can handle local STT_GNU_IFUNC symbols
 
  as global symbol.  We reuse indx and dynstr_index for local symbol
 
  hash since they aren't used by global symbols in this backend.  */
 
 
 
static hashval_t
 
elf_i386_local_htab_hash (const void *ptr)
 
{
 
  struct elf_link_hash_entry *h
 
    = (struct elf_link_hash_entry *) ptr;
 
  return ELF_LOCAL_SYMBOL_HASH (h->indx, h->dynstr_index);
 
}
 
 
 
/* Compare local hash entries.  */
 
 
 
static int
 
elf_i386_local_htab_eq (const void *ptr1, const void *ptr2)
 
{
 
  struct elf_link_hash_entry *h1
 
     = (struct elf_link_hash_entry *) ptr1;
 
  struct elf_link_hash_entry *h2
 
    = (struct elf_link_hash_entry *) ptr2;
 
 
 
  return h1->indx == h2->indx && h1->dynstr_index == h2->dynstr_index;
 
}
 
 
 
/* Find and/or create a hash entry for local symbol.  */
 
 
 
static struct elf_link_hash_entry *
 
elf_i386_get_local_sym_hash (struct elf_i386_link_hash_table *htab,
 
                             bfd *abfd, const Elf_Internal_Rela *rel,
 
                             bfd_boolean create)
 
{
 
  struct elf_i386_link_hash_entry e, *ret;
 
  asection *sec = abfd->sections;
 
  hashval_t h = ELF_LOCAL_SYMBOL_HASH (sec->id,
 
                                       ELF32_R_SYM (rel->r_info));
 
  void **slot;
 
 
 
  e.elf.indx = sec->id;
 
  e.elf.dynstr_index = ELF32_R_SYM (rel->r_info);
 
  slot = htab_find_slot_with_hash (htab->loc_hash_table, &e, h,
 
                                   create ? INSERT : NO_INSERT);
 
 
 
  if (!slot)
 
    return NULL;
 
 
 
  if (*slot)
 
    {
 
      ret = (struct elf_i386_link_hash_entry *) *slot;
 
      return &ret->elf;
 
    }
 
 
 
  ret = (struct elf_i386_link_hash_entry *)
 
        objalloc_alloc ((struct objalloc *) htab->loc_hash_memory,
 
                        sizeof (struct elf_i386_link_hash_entry));
 
  if (ret)
 
    {
 
      memset (ret, 0, sizeof (*ret));
 
      ret->elf.indx = sec->id;
 
      ret->elf.dynstr_index = ELF32_R_SYM (rel->r_info);
 
      ret->elf.dynindx = -1;
 
      ret->elf.plt.offset = (bfd_vma) -1;
 
      ret->elf.got.offset = (bfd_vma) -1;
 
      *slot = ret;
 
    }
 
  return &ret->elf;
 
}
 
 
/* Create an i386 ELF linker hash table.  */
/* Create an i386 ELF linker hash table.  */
 
 
static struct bfd_link_hash_table *
static struct bfd_link_hash_table *
elf_i386_link_hash_table_create (bfd *abfd)
elf_i386_link_hash_table_create (bfd *abfd)
{
{
  struct elf_i386_link_hash_table *ret;
  struct elf_i386_link_hash_table *ret;
  bfd_size_type amt = sizeof (struct elf_i386_link_hash_table);
  bfd_size_type amt = sizeof (struct elf_i386_link_hash_table);
 
 
  ret = bfd_malloc (amt);
  ret = (struct elf_i386_link_hash_table *) bfd_malloc (amt);
  if (ret == NULL)
  if (ret == NULL)
    return NULL;
    return NULL;
 
 
  if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
  if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd,
 
                                      elf_i386_link_hash_newfunc,
                                      sizeof (struct elf_i386_link_hash_entry)))
                                      sizeof (struct elf_i386_link_hash_entry)))
    {
    {
      free (ret);
      free (ret);
      return NULL;
      return NULL;
    }
    }
 
 
  ret->sgot = NULL;
 
  ret->sgotplt = NULL;
 
  ret->srelgot = NULL;
 
  ret->splt = NULL;
 
  ret->srelplt = NULL;
 
  ret->sdynbss = NULL;
  ret->sdynbss = NULL;
  ret->srelbss = NULL;
  ret->srelbss = NULL;
  ret->tls_ldm_got.refcount = 0;
  ret->tls_ldm_got.refcount = 0;
  ret->next_tls_desc_index = 0;
  ret->next_tls_desc_index = 0;
  ret->sgotplt_jump_table_size = 0;
  ret->sgotplt_jump_table_size = 0;
  ret->sym_sec.abfd = NULL;
  ret->sym_cache.abfd = NULL;
  ret->is_vxworks = 0;
  ret->is_vxworks = 0;
  ret->srelplt2 = NULL;
  ret->srelplt2 = NULL;
  ret->plt0_pad_byte = 0;
  ret->plt0_pad_byte = 0;
 
  ret->tls_module_base = NULL;
 
 
 
  ret->loc_hash_table = htab_try_create (1024,
 
                                         elf_i386_local_htab_hash,
 
                                         elf_i386_local_htab_eq,
 
                                         NULL);
 
  ret->loc_hash_memory = objalloc_create ();
 
  if (!ret->loc_hash_table || !ret->loc_hash_memory)
 
    {
 
      free (ret);
 
      return NULL;
 
    }
 
 
  return &ret->elf.root;
  return &ret->elf.root;
}
}
 
 
/* Create .got, .gotplt, and .rel.got sections in DYNOBJ, and set up
/* Destroy an i386 ELF linker hash table.  */
   shortcuts to them in our hash table.  */
 
 
 
static bfd_boolean
static void
create_got_section (bfd *dynobj, struct bfd_link_info *info)
elf_i386_link_hash_table_free (struct bfd_link_hash_table *hash)
{
{
  struct elf_i386_link_hash_table *htab;
  struct elf_i386_link_hash_table *htab
 
    = (struct elf_i386_link_hash_table *) hash;
  if (! _bfd_elf_create_got_section (dynobj, info))
 
    return FALSE;
 
 
 
  htab = elf_i386_hash_table (info);
 
  htab->sgot = bfd_get_section_by_name (dynobj, ".got");
 
  htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
 
  if (!htab->sgot || !htab->sgotplt)
 
    abort ();
 
 
 
  htab->srelgot = bfd_make_section_with_flags (dynobj, ".rel.got",
  if (htab->loc_hash_table)
                                               (SEC_ALLOC | SEC_LOAD
    htab_delete (htab->loc_hash_table);
                                                | SEC_HAS_CONTENTS
  if (htab->loc_hash_memory)
                                                | SEC_IN_MEMORY
    objalloc_free ((struct objalloc *) htab->loc_hash_memory);
                                                | SEC_LINKER_CREATED
  _bfd_generic_link_hash_table_free (hash);
                                                | SEC_READONLY));
 
  if (htab->srelgot == NULL
 
      || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2))
 
    return FALSE;
 
  return TRUE;
 
}
}
 
 
/* Create .plt, .rel.plt, .got, .got.plt, .rel.got, .dynbss, and
/* Create .plt, .rel.plt, .got, .got.plt, .rel.got, .dynbss, and
   .rel.bss sections in DYNOBJ, and set up shortcuts to them in our
   .rel.bss sections in DYNOBJ, and set up shortcuts to them in our
   hash table.  */
   hash table.  */
Line 807... Line 861...
static bfd_boolean
static bfd_boolean
elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
{
{
  struct elf_i386_link_hash_table *htab;
  struct elf_i386_link_hash_table *htab;
 
 
  htab = elf_i386_hash_table (info);
 
  if (!htab->sgot && !create_got_section (dynobj, info))
 
    return FALSE;
 
 
 
  if (!_bfd_elf_create_dynamic_sections (dynobj, info))
  if (!_bfd_elf_create_dynamic_sections (dynobj, info))
    return FALSE;
    return FALSE;
 
 
  htab->splt = bfd_get_section_by_name (dynobj, ".plt");
  htab = elf_i386_hash_table (info);
  htab->srelplt = bfd_get_section_by_name (dynobj, ".rel.plt");
 
  htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
  htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
  if (!info->shared)
  if (!info->shared)
    htab->srelbss = bfd_get_section_by_name (dynobj, ".rel.bss");
    htab->srelbss = bfd_get_section_by_name (dynobj, ".rel.bss");
 
 
  if (!htab->splt || !htab->srelplt || !htab->sdynbss
  if (!htab->sdynbss
      || (!info->shared && !htab->srelbss))
      || (!info->shared && !htab->srelbss))
    abort ();
    abort ();
 
 
  if (htab->is_vxworks
  if (htab->is_vxworks
      && !elf_vxworks_create_dynamic_sections (dynobj, info, &htab->srelplt2))
      && !elf_vxworks_create_dynamic_sections (dynobj, info,
 
                                               &htab->srelplt2))
    return FALSE;
    return FALSE;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
Line 847... Line 897...
 
 
  if (eind->dyn_relocs != NULL)
  if (eind->dyn_relocs != NULL)
    {
    {
      if (edir->dyn_relocs != NULL)
      if (edir->dyn_relocs != NULL)
        {
        {
          struct elf_i386_dyn_relocs **pp;
          struct elf_dyn_relocs **pp;
          struct elf_i386_dyn_relocs *p;
          struct elf_dyn_relocs *p;
 
 
          /* Add reloc counts against the indirect sym to the direct sym
          /* Add reloc counts against the indirect sym to the direct sym
             list.  Merge any entries against the same section.  */
             list.  Merge any entries against the same section.  */
          for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
          for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
            {
            {
              struct elf_i386_dyn_relocs *q;
              struct elf_dyn_relocs *q;
 
 
              for (q = edir->dyn_relocs; q != NULL; q = q->next)
              for (q = edir->dyn_relocs; q != NULL; q = q->next)
                if (q->sec == p->sec)
                if (q->sec == p->sec)
                  {
                  {
                    q->pc_count += p->pc_count;
                    q->pc_count += p->pc_count;
Line 949... Line 999...
        return FALSE;
        return FALSE;
 
 
      type = bfd_get_8 (abfd, contents + offset - 2);
      type = bfd_get_8 (abfd, contents + offset - 2);
      if (r_type == R_386_TLS_GD)
      if (r_type == R_386_TLS_GD)
        {
        {
          /* Check transition from LD access model.  Only
          /* Check transition from GD access model.  Only
                leal foo@tlsgd(,%reg,1), %eax; call ___tls_get_addr
                leal foo@tlsgd(,%reg,1), %eax; call ___tls_get_addr
                leal foo@tlsgd(%reg), %eax; call ___tls_get_addr; nop
                leal foo@tlsgd(%reg), %eax; call ___tls_get_addr; nop
             can transit to different access model.  */
             can transit to different access model.  */
          if ((offset + 10) > sec->size ||
          if ((offset + 10) > sec->size ||
              (type != 0x8d && type != 0x04))
              (type != 0x8d && type != 0x04))
Line 1001... Line 1051...
      r_symndx = ELF32_R_SYM (rel[1].r_info);
      r_symndx = ELF32_R_SYM (rel[1].r_info);
      if (r_symndx < symtab_hdr->sh_info)
      if (r_symndx < symtab_hdr->sh_info)
        return FALSE;
        return FALSE;
 
 
      h = sym_hashes[r_symndx - symtab_hdr->sh_info];
      h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 
      /* Use strncmp to check ___tls_get_addr since ___tls_get_addr
 
         may be versioned.  */
      return (h != NULL
      return (h != NULL
              && h->root.root.string != NULL
              && h->root.root.string != NULL
              && (ELF32_R_TYPE (rel[1].r_info) == R_386_PC32
              && (ELF32_R_TYPE (rel[1].r_info) == R_386_PC32
                  || ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32)
                  || ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32)
              && (strcmp (h->root.root.string, "___tls_get_addr") == 0));
              && (strncmp (h->root.root.string, "___tls_get_addr",
 
                           15) == 0));
 
 
    case R_386_TLS_IE:
    case R_386_TLS_IE:
      /* Check transition from IE access model:
      /* Check transition from IE access model:
                movl foo@indntpoff(%rip), %eax
                movl foo@indntpoff(%rip), %eax
                movl foo@indntpoff(%rip), %reg
                movl foo@indntpoff(%rip), %reg
Line 1094... Line 1147...
                         Elf_Internal_Shdr *symtab_hdr,
                         Elf_Internal_Shdr *symtab_hdr,
                         struct elf_link_hash_entry **sym_hashes,
                         struct elf_link_hash_entry **sym_hashes,
                         unsigned int *r_type, int tls_type,
                         unsigned int *r_type, int tls_type,
                         const Elf_Internal_Rela *rel,
                         const Elf_Internal_Rela *rel,
                         const Elf_Internal_Rela *relend,
                         const Elf_Internal_Rela *relend,
                         struct elf_link_hash_entry *h)
                         struct elf_link_hash_entry *h,
 
                         unsigned long r_symndx)
{
{
  unsigned int from_type = *r_type;
  unsigned int from_type = *r_type;
  unsigned int to_type = from_type;
  unsigned int to_type = from_type;
  bfd_boolean check = TRUE;
  bfd_boolean check = TRUE;
 
 
Line 1108... Line 1162...
    case R_386_TLS_GOTDESC:
    case R_386_TLS_GOTDESC:
    case R_386_TLS_DESC_CALL:
    case R_386_TLS_DESC_CALL:
    case R_386_TLS_IE_32:
    case R_386_TLS_IE_32:
    case R_386_TLS_IE:
    case R_386_TLS_IE:
    case R_386_TLS_GOTIE:
    case R_386_TLS_GOTIE:
      if (!info->shared)
      if (info->executable)
        {
        {
          if (h == NULL)
          if (h == NULL)
            to_type = R_386_TLS_LE_32;
            to_type = R_386_TLS_LE_32;
          else if (from_type != R_386_TLS_IE
          else if (from_type != R_386_TLS_IE
                   && from_type != R_386_TLS_GOTIE)
                   && from_type != R_386_TLS_GOTIE)
Line 1124... Line 1178...
         TLS_TYPE.  */
         TLS_TYPE.  */
      if (contents != NULL)
      if (contents != NULL)
        {
        {
          unsigned int new_to_type = to_type;
          unsigned int new_to_type = to_type;
 
 
          if (!info->shared
          if (info->executable
              && h != NULL
              && h != NULL
              && h->dynindx == -1
              && h->dynindx == -1
              && (tls_type & GOT_TLS_IE))
              && (tls_type & GOT_TLS_IE))
            new_to_type = R_386_TLS_LE_32;
            new_to_type = R_386_TLS_LE_32;
 
 
Line 1150... Line 1204...
        }
        }
 
 
      break;
      break;
 
 
    case R_386_TLS_LDM:
    case R_386_TLS_LDM:
      if (!info->shared)
      if (info->executable)
        to_type = R_386_TLS_LE_32;
        to_type = R_386_TLS_LE_32;
      break;
      break;
 
 
    default:
    default:
      return TRUE;
      return TRUE;
Line 1169... Line 1223...
      && ! elf_i386_check_tls_transition (abfd, sec, contents,
      && ! elf_i386_check_tls_transition (abfd, sec, contents,
                                          symtab_hdr, sym_hashes,
                                          symtab_hdr, sym_hashes,
                                          from_type, rel, relend))
                                          from_type, rel, relend))
    {
    {
      reloc_howto_type *from, *to;
      reloc_howto_type *from, *to;
 
      const char *name;
 
 
      from = elf_i386_rtype_to_howto (abfd, from_type);
      from = elf_i386_rtype_to_howto (abfd, from_type);
      to = elf_i386_rtype_to_howto (abfd, to_type);
      to = elf_i386_rtype_to_howto (abfd, to_type);
 
 
 
      if (h)
 
        name = h->root.root.string;
 
      else
 
        {
 
          Elf_Internal_Sym *isym;
 
          struct elf_i386_link_hash_table *htab;
 
          htab = elf_i386_hash_table (info);
 
          isym = bfd_sym_from_r_symndx (&htab->sym_cache,
 
                                        abfd, r_symndx);
 
          name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
 
        }
 
 
      (*_bfd_error_handler)
      (*_bfd_error_handler)
        (_("%B: TLS transition from %s to %s against `%s' at 0x%lx "
        (_("%B: TLS transition from %s to %s against `%s' at 0x%lx "
           "in section `%A' failed"),
           "in section `%A' failed"),
         abfd, sec, from->name, to->name,
         abfd, sec, from->name, to->name, name,
         h ? h->root.root.string : "a local symbol",
 
         (unsigned long) rel->r_offset);
         (unsigned long) rel->r_offset);
      bfd_set_error (bfd_error_bad_value);
      bfd_set_error (bfd_error_bad_value);
      return FALSE;
      return FALSE;
    }
    }
 
 
Line 1221... Line 1287...
  for (rel = relocs; rel < rel_end; rel++)
  for (rel = relocs; rel < rel_end; rel++)
    {
    {
      unsigned int r_type;
      unsigned int r_type;
      unsigned long r_symndx;
      unsigned long r_symndx;
      struct elf_link_hash_entry *h;
      struct elf_link_hash_entry *h;
 
      Elf_Internal_Sym *isym;
 
      const char *name;
 
 
      r_symndx = ELF32_R_SYM (rel->r_info);
      r_symndx = ELF32_R_SYM (rel->r_info);
      r_type = ELF32_R_TYPE (rel->r_info);
      r_type = ELF32_R_TYPE (rel->r_info);
 
 
      if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
      if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
Line 1234... Line 1302...
                                 r_symndx);
                                 r_symndx);
          return FALSE;
          return FALSE;
        }
        }
 
 
      if (r_symndx < symtab_hdr->sh_info)
      if (r_symndx < symtab_hdr->sh_info)
 
        {
 
          /* A local symbol.  */
 
          isym = bfd_sym_from_r_symndx (&htab->sym_cache,
 
                                        abfd, r_symndx);
 
          if (isym == NULL)
 
            return FALSE;
 
 
 
          /* Check relocation against local STT_GNU_IFUNC symbol.  */
 
          if (ELF32_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
 
            {
 
              h = elf_i386_get_local_sym_hash (htab, abfd, rel,
 
                                                   TRUE);
 
              if (h == NULL)
 
                return FALSE;
 
 
 
              /* Fake a STT_GNU_IFUNC symbol.  */
 
              h->type = STT_GNU_IFUNC;
 
              h->def_regular = 1;
 
              h->ref_regular = 1;
 
              h->forced_local = 1;
 
              h->root.type = bfd_link_hash_defined;
 
            }
 
          else
        h = NULL;
        h = NULL;
 
        }
      else
      else
        {
        {
 
          isym = NULL;
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
          while (h->root.type == bfd_link_hash_indirect
          while (h->root.type == bfd_link_hash_indirect
                 || h->root.type == bfd_link_hash_warning)
                 || h->root.type == bfd_link_hash_warning)
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
        }
        }
 
 
 
      if (h != NULL)
 
        {
 
          /* Create the ifunc sections for static executables.  If we
 
             never see an indirect function symbol nor we are building
 
             a static executable, those sections will be empty and
 
             won't appear in output.  */
 
          switch (r_type)
 
            {
 
            default:
 
              break;
 
 
 
            case R_386_32:
 
            case R_386_PC32:
 
            case R_386_PLT32:
 
            case R_386_GOT32:
 
            case R_386_GOTOFF:
 
              if (!_bfd_elf_create_ifunc_sections (abfd, info))
 
                return FALSE;
 
              break;
 
            }
 
 
 
          /* Since STT_GNU_IFUNC symbol must go through PLT, we handle
 
             it here if it is defined in a non-shared object.  */
 
          if (h->type == STT_GNU_IFUNC
 
              && h->def_regular)
 
            {
 
              /* It is referenced by a non-shared object. */
 
              h->ref_regular = 1;
 
              h->needs_plt = 1;
 
 
 
              /* STT_GNU_IFUNC symbol must go through PLT.  */
 
              h->plt.refcount += 1;
 
 
 
              /* STT_GNU_IFUNC needs dynamic sections.  */
 
              if (htab->elf.dynobj == NULL)
 
                htab->elf.dynobj = abfd;
 
 
 
              switch (r_type)
 
                {
 
                default:
 
                  if (h->root.root.string)
 
                    name = h->root.root.string;
 
                  else
 
                    name = bfd_elf_sym_name (abfd, symtab_hdr, isym,
 
                                             NULL);
 
                  (*_bfd_error_handler)
 
                    (_("%B: relocation %s against STT_GNU_IFUNC "
 
                       "symbol `%s' isn't handled by %s"), abfd,
 
                     elf_howto_table[r_type].name,
 
                     name, __FUNCTION__);
 
                  bfd_set_error (bfd_error_bad_value);
 
                  return FALSE;
 
 
 
                case R_386_32:
 
                  h->non_got_ref = 1;
 
                  h->pointer_equality_needed = 1;
 
                  if (info->shared)
 
                    {
 
                      /* We must copy these reloc types into the
 
                         output file.  Create a reloc section in
 
                         dynobj and make room for this reloc.  */
 
                      sreloc = _bfd_elf_create_ifunc_dyn_reloc
 
                        (abfd, info, sec, sreloc,
 
                         &((struct elf_i386_link_hash_entry *) h)->dyn_relocs);
 
                      if (sreloc == NULL)
 
                        return FALSE;
 
                    }
 
                  break;
 
 
 
                case R_386_PC32:
 
                  h->non_got_ref = 1;
 
                  break;
 
 
 
                case R_386_PLT32:
 
                  break;
 
 
 
                case R_386_GOT32:
 
                case R_386_GOTOFF:
 
                  h->got.refcount += 1;
 
                  if (htab->elf.sgot == NULL
 
                      && !_bfd_elf_create_got_section (htab->elf.dynobj,
 
                                                       info))
 
                    return FALSE;
 
                  break;
 
                }
 
 
 
              continue;
 
            }
 
        }
 
 
      if (! elf_i386_tls_transition (info, abfd, sec, NULL,
      if (! elf_i386_tls_transition (info, abfd, sec, NULL,
                                     symtab_hdr, sym_hashes,
                                     symtab_hdr, sym_hashes,
                                     &r_type, GOT_UNKNOWN,
                                     &r_type, GOT_UNKNOWN,
                                     rel, rel_end, h))
                                     rel, rel_end, h, r_symndx))
        return FALSE;
        return FALSE;
 
 
      switch (r_type)
      switch (r_type)
        {
        {
        case R_386_TLS_LDM:
        case R_386_TLS_LDM:
Line 1275... Line 1458...
          break;
          break;
 
 
        case R_386_TLS_IE_32:
        case R_386_TLS_IE_32:
        case R_386_TLS_IE:
        case R_386_TLS_IE:
        case R_386_TLS_GOTIE:
        case R_386_TLS_GOTIE:
          if (info->shared)
          if (!info->executable)
            info->flags |= DF_STATIC_TLS;
            info->flags |= DF_STATIC_TLS;
          /* Fall through */
          /* Fall through */
 
 
        case R_386_GOT32:
        case R_386_GOT32:
        case R_386_TLS_GD:
        case R_386_TLS_GD:
Line 1326... Line 1509...
                    bfd_size_type size;
                    bfd_size_type size;
 
 
                    size = symtab_hdr->sh_info;
                    size = symtab_hdr->sh_info;
                    size *= (sizeof (bfd_signed_vma)
                    size *= (sizeof (bfd_signed_vma)
                             + sizeof (bfd_vma) + sizeof(char));
                             + sizeof (bfd_vma) + sizeof(char));
                    local_got_refcounts = bfd_zalloc (abfd, size);
                    local_got_refcounts = (bfd_signed_vma *)
 
                        bfd_zalloc (abfd, size);
                    if (local_got_refcounts == NULL)
                    if (local_got_refcounts == NULL)
                      return FALSE;
                      return FALSE;
                    elf_local_got_refcounts (abfd) = local_got_refcounts;
                    elf_local_got_refcounts (abfd) = local_got_refcounts;
                    elf_i386_local_tlsdesc_gotent (abfd)
                    elf_i386_local_tlsdesc_gotent (abfd)
                      = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info);
                      = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info);
Line 1354... Line 1538...
                else if (GOT_TLS_GD_ANY_P (old_tls_type)
                else if (GOT_TLS_GD_ANY_P (old_tls_type)
                         && GOT_TLS_GD_ANY_P (tls_type))
                         && GOT_TLS_GD_ANY_P (tls_type))
                  tls_type |= old_tls_type;
                  tls_type |= old_tls_type;
                else
                else
                  {
                  {
 
                    if (h)
 
                      name = h->root.root.string;
 
                    else
 
                      name = bfd_elf_sym_name (abfd, symtab_hdr, isym,
 
                                             NULL);
                    (*_bfd_error_handler)
                    (*_bfd_error_handler)
                      (_("%B: `%s' accessed both as normal and "
                      (_("%B: `%s' accessed both as normal and "
                         "thread local symbol"),
                         "thread local symbol"),
                       abfd,
                       abfd, name);
                       h ? h->root.root.string : "<local>");
 
                    return FALSE;
                    return FALSE;
                  }
                  }
              }
              }
 
 
            if (old_tls_type != tls_type)
            if (old_tls_type != tls_type)
Line 1376... Line 1564...
          /* Fall through */
          /* Fall through */
 
 
        case R_386_GOTOFF:
        case R_386_GOTOFF:
        case R_386_GOTPC:
        case R_386_GOTPC:
        create_got:
        create_got:
          if (htab->sgot == NULL)
          if (htab->elf.sgot == NULL)
            {
            {
              if (htab->elf.dynobj == NULL)
              if (htab->elf.dynobj == NULL)
                htab->elf.dynobj = abfd;
                htab->elf.dynobj = abfd;
              if (!create_got_section (htab->elf.dynobj, info))
              if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
                return FALSE;
                return FALSE;
            }
            }
          if (r_type != R_386_TLS_IE)
          if (r_type != R_386_TLS_IE)
            break;
            break;
          /* Fall through */
          /* Fall through */
 
 
        case R_386_TLS_LE_32:
        case R_386_TLS_LE_32:
        case R_386_TLS_LE:
        case R_386_TLS_LE:
          if (!info->shared)
          if (info->executable)
            break;
            break;
          info->flags |= DF_STATIC_TLS;
          info->flags |= DF_STATIC_TLS;
          /* Fall through */
          /* Fall through */
 
 
        case R_386_32:
        case R_386_32:
        case R_386_PC32:
        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
              /* If this reloc is in a read-only section, we might
                 need a copy reloc.  We can't check reliably at this
                 need a copy reloc.  We can't check reliably at this
                 stage whether the section is read-only, as input
                 stage whether the section is read-only, as input
                 sections have not yet been mapped to output sections.
                 sections have not yet been mapped to output sections.
Line 1448... Line 1636...
                  && (sec->flags & SEC_ALLOC) != 0
                  && (sec->flags & SEC_ALLOC) != 0
                  && h != NULL
                  && h != NULL
                  && (h->root.type == bfd_link_hash_defweak
                  && (h->root.type == bfd_link_hash_defweak
                      || !h->def_regular)))
                      || !h->def_regular)))
            {
            {
              struct elf_i386_dyn_relocs *p;
              struct elf_dyn_relocs *p;
              struct elf_i386_dyn_relocs **head;
              struct elf_dyn_relocs **head;
 
 
              /* We must copy these reloc types into the output file.
              /* We must copy these reloc types into the output file.
                 Create a reloc section in dynobj and make room for
                 Create a reloc section in dynobj and make room for
                 this reloc.  */
                 this reloc.  */
              if (sreloc == NULL)
              if (sreloc == NULL)
                {
                {
                  const char *name;
 
                  bfd *dynobj;
 
                  unsigned int strndx = elf_elfheader (abfd)->e_shstrndx;
 
                  unsigned int shnam = elf_section_data (sec)->rel_hdr.sh_name;
 
 
 
                  name = bfd_elf_string_from_elf_section (abfd, strndx, shnam);
 
                  if (name == NULL)
 
                    return FALSE;
 
 
 
                  if (! CONST_STRNEQ (name, ".rel")
 
                      || strcmp (bfd_get_section_name (abfd, sec),
 
                                 name + 4) != 0)
 
                    {
 
                      (*_bfd_error_handler)
 
                        (_("%B: bad relocation section name `%s\'"),
 
                         abfd, name);
 
                    }
 
 
 
                  if (htab->elf.dynobj == NULL)
                  if (htab->elf.dynobj == NULL)
                    htab->elf.dynobj = abfd;
                    htab->elf.dynobj = abfd;
 
 
                  dynobj = htab->elf.dynobj;
                  sreloc = _bfd_elf_make_dynamic_reloc_section
                  sreloc = bfd_get_section_by_name (dynobj, name);
                    (sec, htab->elf.dynobj, 2, abfd, /*rela?*/ FALSE);
                  if (sreloc == NULL)
 
                    {
 
                      flagword flags;
 
 
 
                      flags = (SEC_HAS_CONTENTS | SEC_READONLY
                  if (sreloc == NULL)
                               | SEC_IN_MEMORY | SEC_LINKER_CREATED);
 
                      if ((sec->flags & SEC_ALLOC) != 0)
 
                        flags |= SEC_ALLOC | SEC_LOAD;
 
                      sreloc = bfd_make_section_with_flags (dynobj,
 
                                                            name,
 
                                                            flags);
 
                      if (sreloc == NULL
 
                          || ! bfd_set_section_alignment (dynobj, sreloc, 2))
 
                        return FALSE;
                        return FALSE;
                    }
                    }
                  elf_section_data (sec)->sreloc = sreloc;
 
                }
 
 
 
              /* If this is a global symbol, we count the number of
              /* If this is a global symbol, we count the number of
                 relocations we need for this symbol.  */
                 relocations we need for this symbol.  */
              if (h != NULL)
              if (h != NULL)
                {
                {
                  head = &((struct elf_i386_link_hash_entry *) h)->dyn_relocs;
                  head = &((struct elf_i386_link_hash_entry *) h)->dyn_relocs;
                }
                }
              else
              else
                {
                {
                  void **vpp;
 
                  /* Track dynamic relocs needed for local syms too.
                  /* Track dynamic relocs needed for local syms too.
                     We really need local syms available to do this
                     We really need local syms available to do this
                     easily.  Oh well.  */
                     easily.  Oh well.  */
 
                  void **vpp;
                  asection *s;
                  asection *s;
                  s = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
                  Elf_Internal_Sym *isym;
                                                 sec, r_symndx);
 
                  if (s == NULL)
                  isym = bfd_sym_from_r_symndx (&htab->sym_cache,
 
                                                abfd, r_symndx);
 
                  if (isym == NULL)
                    return FALSE;
                    return FALSE;
 
 
 
                  s = bfd_section_from_elf_index (abfd, isym->st_shndx);
 
                  if (s == NULL)
 
                    s = sec;
 
 
                  vpp = &elf_section_data (s)->local_dynrel;
                  vpp = &elf_section_data (s)->local_dynrel;
                  head = (struct elf_i386_dyn_relocs **)vpp;
                  head = (struct elf_dyn_relocs **)vpp;
                }
                }
 
 
              p = *head;
              p = *head;
              if (p == NULL || p->sec != sec)
              if (p == NULL || p->sec != sec)
                {
                {
                  bfd_size_type amt = sizeof *p;
                  bfd_size_type amt = sizeof *p;
                  p = bfd_alloc (htab->elf.dynobj, amt);
                  p = (struct elf_dyn_relocs *) bfd_alloc (htab->elf.dynobj,
 
                                                           amt);
                  if (p == NULL)
                  if (p == NULL)
                    return FALSE;
                    return FALSE;
                  p->next = *head;
                  p->next = *head;
                  *head = p;
                  *head = p;
                  p->sec = sec;
                  p->sec = sec;
Line 1618... Line 1781...
 
 
      r_symndx = ELF32_R_SYM (rel->r_info);
      r_symndx = ELF32_R_SYM (rel->r_info);
      if (r_symndx >= symtab_hdr->sh_info)
      if (r_symndx >= symtab_hdr->sh_info)
        {
        {
          struct elf_i386_link_hash_entry *eh;
          struct elf_i386_link_hash_entry *eh;
          struct elf_i386_dyn_relocs **pp;
          struct elf_dyn_relocs **pp;
          struct elf_i386_dyn_relocs *p;
          struct elf_dyn_relocs *p;
 
 
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
          h = sym_hashes[r_symndx - symtab_hdr->sh_info];
          while (h->root.type == bfd_link_hash_indirect
          while (h->root.type == bfd_link_hash_indirect
                 || h->root.type == bfd_link_hash_warning)
                 || h->root.type == bfd_link_hash_warning)
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
            h = (struct elf_link_hash_entry *) h->root.u.i.link;
Line 1640... Line 1803...
 
 
      r_type = ELF32_R_TYPE (rel->r_info);
      r_type = ELF32_R_TYPE (rel->r_info);
      if (! elf_i386_tls_transition (info, abfd, sec, NULL,
      if (! elf_i386_tls_transition (info, abfd, sec, NULL,
                                     symtab_hdr, sym_hashes,
                                     symtab_hdr, sym_hashes,
                                     &r_type, GOT_UNKNOWN,
                                     &r_type, GOT_UNKNOWN,
                                     rel, relend, h))
                                     rel, relend, h, r_symndx))
        return FALSE;
        return FALSE;
 
 
      switch (r_type)
      switch (r_type)
        {
        {
        case R_386_TLS_LDM:
        case R_386_TLS_LDM:
Line 1704... Line 1867...
                                struct elf_link_hash_entry *h)
                                struct elf_link_hash_entry *h)
{
{
  struct elf_i386_link_hash_table *htab;
  struct elf_i386_link_hash_table *htab;
  asection *s;
  asection *s;
 
 
 
  /* STT_GNU_IFUNC symbol must go through PLT. */
 
  if (h->type == STT_GNU_IFUNC)
 
    {
 
      if (h->plt.refcount <= 0)
 
        {
 
          h->plt.offset = (bfd_vma) -1;
 
          h->needs_plt = 0;
 
        }
 
      return TRUE;
 
    }
 
 
  /* If this is a function, put it in the procedure linkage table.  We
  /* If this is a function, put it in the procedure linkage table.  We
     will fill in the contents of the procedure linkage table later,
     will fill in the contents of the procedure linkage table later,
     when we know the address of the .got section.  */
     when we know the address of the .got section.  */
  if (h->type == STT_FUNC
  if (h->type == STT_FUNC
      || h->needs_plt)
      || h->needs_plt)
Line 1779... Line 1953...
     doesn't work on VxWorks, where we can not have dynamic relocations
     doesn't work on VxWorks, where we can not have dynamic relocations
     (other than copy and jump slot relocations) in an executable.  */
     (other than copy and jump slot relocations) in an executable.  */
  if (ELIMINATE_COPY_RELOCS && !htab->is_vxworks)
  if (ELIMINATE_COPY_RELOCS && !htab->is_vxworks)
    {
    {
      struct elf_i386_link_hash_entry * eh;
      struct elf_i386_link_hash_entry * eh;
      struct elf_i386_dyn_relocs *p;
      struct elf_dyn_relocs *p;
 
 
      eh = (struct elf_i386_link_hash_entry *) h;
      eh = (struct elf_i386_link_hash_entry *) h;
      for (p = eh->dyn_relocs; p != NULL; p = p->next)
      for (p = eh->dyn_relocs; p != NULL; p = p->next)
        {
        {
          s = p->sec->output_section;
          s = p->sec->output_section;
Line 1831... Line 2005...
 
 
/* Allocate space in .plt, .got and associated reloc sections for
/* Allocate space in .plt, .got and associated reloc sections for
   dynamic relocs.  */
   dynamic relocs.  */
 
 
static bfd_boolean
static bfd_boolean
allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
{
{
  struct bfd_link_info *info;
  struct bfd_link_info *info;
  struct elf_i386_link_hash_table *htab;
  struct elf_i386_link_hash_table *htab;
  struct elf_i386_link_hash_entry *eh;
  struct elf_i386_link_hash_entry *eh;
  struct elf_i386_dyn_relocs *p;
  struct elf_dyn_relocs *p;
 
 
  if (h->root.type == bfd_link_hash_indirect)
  if (h->root.type == bfd_link_hash_indirect)
    return TRUE;
    return TRUE;
 
 
  if (h->root.type == bfd_link_hash_warning)
  if (h->root.type == bfd_link_hash_warning)
    /* When warning symbols are created, they **replace** the "real"
    /* When warning symbols are created, they **replace** the "real"
       entry in the hash table, thus we never get to see the real
       entry in the hash table, thus we never get to see the real
       symbol in a hash traversal.  So look at it now.  */
       symbol in a hash traversal.  So look at it now.  */
    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
  eh = (struct elf_i386_link_hash_entry *) h;
 
 
  info = (struct bfd_link_info *) inf;
  info = (struct bfd_link_info *) inf;
  htab = elf_i386_hash_table (info);
  htab = elf_i386_hash_table (info);
 
 
  if (htab->elf.dynamic_sections_created
  /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
 
     here if it is defined and referenced in a non-shared object.  */
 
  if (h->type == STT_GNU_IFUNC
 
      && h->def_regular)
 
    return _bfd_elf_allocate_ifunc_dyn_relocs (info, h,
 
                                               &eh->dyn_relocs,
 
                                               PLT_ENTRY_SIZE, 4);
 
  else if (htab->elf.dynamic_sections_created
      && h->plt.refcount > 0)
      && h->plt.refcount > 0)
    {
    {
      /* Make sure this symbol is output as a dynamic symbol.
      /* Make sure this symbol is output as a dynamic symbol.
         Undefined weak syms won't yet be marked as dynamic.  */
         Undefined weak syms won't yet be marked as dynamic.  */
      if (h->dynindx == -1
      if (h->dynindx == -1
Line 1865... Line 2047...
        }
        }
 
 
      if (info->shared
      if (info->shared
          || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
          || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
        {
        {
          asection *s = htab->splt;
          asection *s = htab->elf.splt;
 
 
          /* If this is the first .plt entry, make room for the special
          /* If this is the first .plt entry, make room for the special
             first entry.  */
             first entry.  */
          if (s->size == 0)
          if (s->size == 0)
            s->size += PLT_ENTRY_SIZE;
            s->size += PLT_ENTRY_SIZE;
Line 1891... Line 2073...
          /* Make room for this entry.  */
          /* Make room for this entry.  */
          s->size += PLT_ENTRY_SIZE;
          s->size += PLT_ENTRY_SIZE;
 
 
          /* We also need to make an entry in the .got.plt section, which
          /* We also need to make an entry in the .got.plt section, which
             will be placed in the .got section by the linker script.  */
             will be placed in the .got section by the linker script.  */
          htab->sgotplt->size += 4;
          htab->elf.sgotplt->size += 4;
 
 
          /* We also need to make an entry in the .rel.plt section.  */
          /* We also need to make an entry in the .rel.plt section.  */
          htab->srelplt->size += sizeof (Elf32_External_Rel);
          htab->elf.srelplt->size += sizeof (Elf32_External_Rel);
          htab->next_tls_desc_index++;
          htab->next_tls_desc_index++;
 
 
          if (htab->is_vxworks && !info->shared)
          if (htab->is_vxworks && !info->shared)
            {
            {
              /* VxWorks has a second set of relocations for each PLT entry
              /* VxWorks has a second set of relocations for each PLT entry
Line 1929... Line 2111...
    {
    {
      h->plt.offset = (bfd_vma) -1;
      h->plt.offset = (bfd_vma) -1;
      h->needs_plt = 0;
      h->needs_plt = 0;
    }
    }
 
 
  eh = (struct elf_i386_link_hash_entry *) h;
 
  eh->tlsdesc_got = (bfd_vma) -1;
  eh->tlsdesc_got = (bfd_vma) -1;
 
 
  /* If R_386_TLS_{IE_32,IE,GOTIE} symbol is now local to the binary,
  /* If R_386_TLS_{IE_32,IE,GOTIE} symbol is now local to the binary,
     make it a R_386_TLS_LE_32 requiring no TLS entry.  */
     make it a R_386_TLS_LE_32 requiring no TLS entry.  */
  if (h->got.refcount > 0
  if (h->got.refcount > 0
      && !info->shared
      && info->executable
      && h->dynindx == -1
      && h->dynindx == -1
      && (elf_i386_hash_entry(h)->tls_type & GOT_TLS_IE))
      && (elf_i386_hash_entry(h)->tls_type & GOT_TLS_IE))
    h->got.offset = (bfd_vma) -1;
    h->got.offset = (bfd_vma) -1;
  else if (h->got.refcount > 0)
  else if (h->got.refcount > 0)
    {
    {
Line 1954... Line 2135...
        {
        {
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
          if (! bfd_elf_link_record_dynamic_symbol (info, h))
            return FALSE;
            return FALSE;
        }
        }
 
 
      s = htab->sgot;
      s = htab->elf.sgot;
      if (GOT_TLS_GDESC_P (tls_type))
      if (GOT_TLS_GDESC_P (tls_type))
        {
        {
          eh->tlsdesc_got = htab->sgotplt->size
          eh->tlsdesc_got = htab->elf.sgotplt->size
            - elf_i386_compute_jump_table_size (htab);
            - elf_i386_compute_jump_table_size (htab);
          htab->sgotplt->size += 8;
          htab->elf.sgotplt->size += 8;
          h->got.offset = (bfd_vma) -2;
          h->got.offset = (bfd_vma) -2;
        }
        }
      if (! GOT_TLS_GDESC_P (tls_type)
      if (! GOT_TLS_GDESC_P (tls_type)
          || GOT_TLS_GD_P (tls_type))
          || GOT_TLS_GD_P (tls_type))
        {
        {
Line 1978... Line 2159...
         R_386_TLS_IE resp. R_386_TLS_GOTIE needs one dynamic relocation,
         R_386_TLS_IE resp. R_386_TLS_GOTIE needs one dynamic relocation,
         (but if both R_386_TLS_IE_32 and R_386_TLS_IE is present, we
         (but if both R_386_TLS_IE_32 and R_386_TLS_IE is present, we
         need two), R_386_TLS_GD needs one if local symbol and two if
         need two), R_386_TLS_GD needs one if local symbol and two if
         global.  */
         global.  */
      if (tls_type == GOT_TLS_IE_BOTH)
      if (tls_type == GOT_TLS_IE_BOTH)
        htab->srelgot->size += 2 * sizeof (Elf32_External_Rel);
        htab->elf.srelgot->size += 2 * sizeof (Elf32_External_Rel);
      else if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1)
      else if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1)
               || (tls_type & GOT_TLS_IE))
               || (tls_type & GOT_TLS_IE))
        htab->srelgot->size += sizeof (Elf32_External_Rel);
        htab->elf.srelgot->size += sizeof (Elf32_External_Rel);
      else if (GOT_TLS_GD_P (tls_type))
      else if (GOT_TLS_GD_P (tls_type))
        htab->srelgot->size += 2 * sizeof (Elf32_External_Rel);
        htab->elf.srelgot->size += 2 * sizeof (Elf32_External_Rel);
      else if (! GOT_TLS_GDESC_P (tls_type)
      else if (! GOT_TLS_GDESC_P (tls_type)
               && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
               && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                   || h->root.type != bfd_link_hash_undefweak)
                   || h->root.type != bfd_link_hash_undefweak)
               && (info->shared
               && (info->shared
                   || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
                   || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
        htab->srelgot->size += sizeof (Elf32_External_Rel);
        htab->elf.srelgot->size += sizeof (Elf32_External_Rel);
      if (GOT_TLS_GDESC_P (tls_type))
      if (GOT_TLS_GDESC_P (tls_type))
        htab->srelplt->size += sizeof (Elf32_External_Rel);
        htab->elf.srelplt->size += sizeof (Elf32_External_Rel);
    }
    }
  else
  else
    h->got.offset = (bfd_vma) -1;
    h->got.offset = (bfd_vma) -1;
 
 
  if (eh->dyn_relocs == NULL)
  if (eh->dyn_relocs == NULL)
Line 2015... Line 2196...
         function rather than going via the plt.  If people want
         function rather than going via the plt.  If people want
         function pointer comparisons to work as expected then they
         function pointer comparisons to work as expected then they
         should avoid writing assembly like ".long foo - .".  */
         should avoid writing assembly like ".long foo - .".  */
      if (SYMBOL_CALLS_LOCAL (info, h))
      if (SYMBOL_CALLS_LOCAL (info, h))
        {
        {
          struct elf_i386_dyn_relocs **pp;
          struct elf_dyn_relocs **pp;
 
 
          for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
          for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
            {
            {
              p->count -= p->pc_count;
              p->count -= p->pc_count;
              p->pc_count = 0;
              p->pc_count = 0;
Line 2028... Line 2209...
              else
              else
                pp = &p->next;
                pp = &p->next;
            }
            }
        }
        }
 
 
 
      if (htab->is_vxworks)
 
        {
 
          struct elf_dyn_relocs **pp;
 
          for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
 
            {
 
              if (strcmp (p->sec->output_section->name, ".tls_vars") == 0)
 
                *pp = p->next;
 
              else
 
                pp = &p->next;
 
            }
 
        }
 
 
      /* Also discard relocs on undefined weak syms with non-default
      /* Also discard relocs on undefined weak syms with non-default
         visibility.  */
         visibility.  */
      if (eh->dyn_relocs != NULL
      if (eh->dyn_relocs != NULL
          && h->root.type == bfd_link_hash_undefweak)
          && h->root.type == bfd_link_hash_undefweak)
        {
        {
Line 2082... Line 2275...
    }
    }
 
 
  /* Finally, allocate space.  */
  /* Finally, allocate space.  */
  for (p = eh->dyn_relocs; p != NULL; p = p->next)
  for (p = eh->dyn_relocs; p != NULL; p = p->next)
    {
    {
      asection *sreloc = elf_section_data (p->sec)->sreloc;
      asection *sreloc;
 
 
 
      sreloc = elf_section_data (p->sec)->sreloc;
 
 
 
      BFD_ASSERT (sreloc != NULL);
      sreloc->size += p->count * sizeof (Elf32_External_Rel);
      sreloc->size += p->count * sizeof (Elf32_External_Rel);
    }
    }
 
 
  return TRUE;
  return TRUE;
}
}
 
 
 
/* Allocate space in .plt, .got and associated reloc sections for
 
   local dynamic relocs.  */
 
 
 
static bfd_boolean
 
elf_i386_allocate_local_dynrelocs (void **slot, void *inf)
 
{
 
  struct elf_link_hash_entry *h
 
    = (struct elf_link_hash_entry *) *slot;
 
 
 
  if (h->type != STT_GNU_IFUNC
 
      || !h->def_regular
 
      || !h->ref_regular
 
      || !h->forced_local
 
      || h->root.type != bfd_link_hash_defined)
 
    abort ();
 
 
 
  return elf_i386_allocate_dynrelocs (h, inf);
 
}
 
 
/* Find any dynamic relocs that apply to read-only sections.  */
/* Find any dynamic relocs that apply to read-only sections.  */
 
 
static bfd_boolean
static bfd_boolean
readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf)
elf_i386_readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf)
{
{
  struct elf_i386_link_hash_entry *eh;
  struct elf_i386_link_hash_entry *eh;
  struct elf_i386_dyn_relocs *p;
  struct elf_dyn_relocs *p;
 
 
  if (h->root.type == bfd_link_hash_warning)
  if (h->root.type == bfd_link_hash_warning)
    h = (struct elf_link_hash_entry *) h->root.u.i.link;
    h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
 
  eh = (struct elf_i386_link_hash_entry *) h;
  eh = (struct elf_i386_link_hash_entry *) h;
Line 2165... Line 2381...
      if (! is_i386_elf (ibfd))
      if (! is_i386_elf (ibfd))
        continue;
        continue;
 
 
      for (s = ibfd->sections; s != NULL; s = s->next)
      for (s = ibfd->sections; s != NULL; s = s->next)
        {
        {
          struct elf_i386_dyn_relocs *p;
          struct elf_dyn_relocs *p;
 
 
          for (p = ((struct elf_i386_dyn_relocs *)
          for (p = ((struct elf_dyn_relocs *)
                     elf_section_data (s)->local_dynrel);
                     elf_section_data (s)->local_dynrel);
               p != NULL;
               p != NULL;
               p = p->next)
               p = p->next)
            {
            {
              if (!bfd_is_abs_section (p->sec)
              if (!bfd_is_abs_section (p->sec)
Line 2180... Line 2396...
                  /* Input section has been discarded, either because
                  /* Input section has been discarded, either because
                     it is a copy of a linkonce section or due to
                     it is a copy of a linkonce section or due to
                     linker script /DISCARD/, so we'll be discarding
                     linker script /DISCARD/, so we'll be discarding
                     the relocs too.  */
                     the relocs too.  */
                }
                }
 
              else if (htab->is_vxworks
 
                       && strcmp (p->sec->output_section->name,
 
                                  ".tls_vars") == 0)
 
                {
 
                  /* Relocations in vxworks .tls_vars sections are
 
                     handled specially by the loader.  */
 
                }
              else if (p->count != 0)
              else if (p->count != 0)
                {
                {
                  srel = elf_section_data (p->sec)->sreloc;
                  srel = elf_section_data (p->sec)->sreloc;
                  srel->size += p->count * sizeof (Elf32_External_Rel);
                  srel->size += p->count * sizeof (Elf32_External_Rel);
                  if ((p->sec->output_section->flags & SEC_READONLY) != 0)
                  if ((p->sec->output_section->flags & SEC_READONLY) != 0)
Line 2199... Line 2422...
      symtab_hdr = &elf_symtab_hdr (ibfd);
      symtab_hdr = &elf_symtab_hdr (ibfd);
      locsymcount = symtab_hdr->sh_info;
      locsymcount = symtab_hdr->sh_info;
      end_local_got = local_got + locsymcount;
      end_local_got = local_got + locsymcount;
      local_tls_type = elf_i386_local_got_tls_type (ibfd);
      local_tls_type = elf_i386_local_got_tls_type (ibfd);
      local_tlsdesc_gotent = elf_i386_local_tlsdesc_gotent (ibfd);
      local_tlsdesc_gotent = elf_i386_local_tlsdesc_gotent (ibfd);
      s = htab->sgot;
      s = htab->elf.sgot;
      srel = htab->srelgot;
      srel = htab->elf.srelgot;
      for (; local_got < end_local_got;
      for (; local_got < end_local_got;
           ++local_got, ++local_tls_type, ++local_tlsdesc_gotent)
           ++local_got, ++local_tls_type, ++local_tlsdesc_gotent)
        {
        {
          *local_tlsdesc_gotent = (bfd_vma) -1;
          *local_tlsdesc_gotent = (bfd_vma) -1;
          if (*local_got > 0)
          if (*local_got > 0)
            {
            {
              if (GOT_TLS_GDESC_P (*local_tls_type))
              if (GOT_TLS_GDESC_P (*local_tls_type))
                {
                {
                  *local_tlsdesc_gotent = htab->sgotplt->size
                  *local_tlsdesc_gotent = htab->elf.sgotplt->size
                    - elf_i386_compute_jump_table_size (htab);
                    - elf_i386_compute_jump_table_size (htab);
                  htab->sgotplt->size += 8;
                  htab->elf.sgotplt->size += 8;
                  *local_got = (bfd_vma) -2;
                  *local_got = (bfd_vma) -2;
                }
                }
              if (! GOT_TLS_GDESC_P (*local_tls_type)
              if (! GOT_TLS_GDESC_P (*local_tls_type)
                  || GOT_TLS_GD_P (*local_tls_type))
                  || GOT_TLS_GD_P (*local_tls_type))
                {
                {
Line 2233... Line 2456...
                    srel->size += 2 * sizeof (Elf32_External_Rel);
                    srel->size += 2 * sizeof (Elf32_External_Rel);
                  else if (GOT_TLS_GD_P (*local_tls_type)
                  else if (GOT_TLS_GD_P (*local_tls_type)
                           || ! GOT_TLS_GDESC_P (*local_tls_type))
                           || ! GOT_TLS_GDESC_P (*local_tls_type))
                    srel->size += sizeof (Elf32_External_Rel);
                    srel->size += sizeof (Elf32_External_Rel);
                  if (GOT_TLS_GDESC_P (*local_tls_type))
                  if (GOT_TLS_GDESC_P (*local_tls_type))
                    htab->srelplt->size += sizeof (Elf32_External_Rel);
                    htab->elf.srelplt->size += sizeof (Elf32_External_Rel);
                }
                }
            }
            }
          else
          else
            *local_got = (bfd_vma) -1;
            *local_got = (bfd_vma) -1;
        }
        }
Line 2245... Line 2468...
 
 
  if (htab->tls_ldm_got.refcount > 0)
  if (htab->tls_ldm_got.refcount > 0)
    {
    {
      /* Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM
      /* Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM
         relocs.  */
         relocs.  */
      htab->tls_ldm_got.offset = htab->sgot->size;
      htab->tls_ldm_got.offset = htab->elf.sgot->size;
      htab->sgot->size += 8;
      htab->elf.sgot->size += 8;
      htab->srelgot->size += sizeof (Elf32_External_Rel);
      htab->elf.srelgot->size += sizeof (Elf32_External_Rel);
    }
    }
  else
  else
    htab->tls_ldm_got.offset = -1;
    htab->tls_ldm_got.offset = -1;
 
 
  /* Allocate global sym .plt and .got entries, and space for global
  /* Allocate global sym .plt and .got entries, and space for global
     sym dynamic relocs.  */
     sym dynamic relocs.  */
  elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
  elf_link_hash_traverse (&htab->elf, elf_i386_allocate_dynrelocs, info);
 
 
 
  /* Allocate .plt and .got entries, and space for local symbols.  */
 
  htab_traverse (htab->loc_hash_table,
 
                 elf_i386_allocate_local_dynrelocs,
 
                 info);
 
 
  /* 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.  */
  if (htab->srelplt)
  if (htab->elf.srelplt)
    htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4;
    htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4;
 
 
  /* We now have determined the sizes of the various dynamic sections.
  /* We now have determined the sizes of the various dynamic sections.
     Allocate memory for them.  */
     Allocate memory for them.  */
  relocs = FALSE;
  relocs = FALSE;
Line 2274... Line 2502...
      bfd_boolean strip_section = TRUE;
      bfd_boolean strip_section = TRUE;
 
 
      if ((s->flags & SEC_LINKER_CREATED) == 0)
      if ((s->flags & SEC_LINKER_CREATED) == 0)
        continue;
        continue;
 
 
      if (s == htab->splt
      if (s == htab->elf.splt
          || s == htab->sgot
          || s == htab->elf.sgot
          || s == htab->sgotplt
          || s == htab->elf.sgotplt
 
          || s == htab->elf.iplt
 
          || s == htab->elf.igotplt
          || s == htab->sdynbss)
          || s == htab->sdynbss)
        {
        {
          /* Strip this section if we don't need it; see the
          /* Strip this section if we don't need it; see the
             comment below.  */
             comment below.  */
          /* We'd like to strip these sections if they aren't needed, but if
          /* We'd like to strip these sections if they aren't needed, but if
Line 2290... Line 2520...
          if (htab->elf.hplt != NULL)
          if (htab->elf.hplt != NULL)
            strip_section = FALSE;
            strip_section = FALSE;
        }
        }
      else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rel"))
      else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rel"))
        {
        {
          if (s->size != 0 && s != htab->srelplt && s != htab->srelplt2)
          if (s->size != 0
 
              && s != htab->elf.srelplt
 
              && s != htab->srelplt2)
            relocs = TRUE;
            relocs = TRUE;
 
 
          /* We use the reloc_count field as a counter if we need
          /* We use the reloc_count field as a counter if we need
             to copy relocs into the output file.  */
             to copy relocs into the output file.  */
          s->reloc_count = 0;
          s->reloc_count = 0;
Line 2327... Line 2559...
      /* Allocate memory for the section contents.  We use bfd_zalloc
      /* Allocate memory for the section contents.  We use bfd_zalloc
         here in case unused entries are not reclaimed before the
         here in case unused entries are not reclaimed before the
         section's contents are written out.  This should not happen,
         section's contents are written out.  This should not happen,
         but this way if it does, we get a R_386_NONE reloc instead
         but this way if it does, we get a R_386_NONE reloc instead
         of garbage.  */
         of garbage.  */
      s->contents = bfd_zalloc (dynobj, s->size);
      s->contents = (unsigned char *) bfd_zalloc (dynobj, s->size);
      if (s->contents == NULL)
      if (s->contents == NULL)
        return FALSE;
        return FALSE;
    }
    }
 
 
  if (htab->elf.dynamic_sections_created)
  if (htab->elf.dynamic_sections_created)
Line 2348... Line 2580...
        {
        {
          if (!add_dynamic_entry (DT_DEBUG, 0))
          if (!add_dynamic_entry (DT_DEBUG, 0))
            return FALSE;
            return FALSE;
        }
        }
 
 
      if (htab->splt->size != 0)
      if (htab->elf.splt->size != 0)
        {
        {
          if (!add_dynamic_entry (DT_PLTGOT, 0)
          if (!add_dynamic_entry (DT_PLTGOT, 0)
              || !add_dynamic_entry (DT_PLTRELSZ, 0)
              || !add_dynamic_entry (DT_PLTRELSZ, 0)
              || !add_dynamic_entry (DT_PLTREL, DT_REL)
              || !add_dynamic_entry (DT_PLTREL, DT_REL)
              || !add_dynamic_entry (DT_JMPREL, 0))
              || !add_dynamic_entry (DT_JMPREL, 0))
Line 2367... Line 2599...
            return FALSE;
            return FALSE;
 
 
          /* If any dynamic relocs apply to a read-only section,
          /* If any dynamic relocs apply to a read-only section,
             then we need a DT_TEXTREL entry.  */
             then we need a DT_TEXTREL entry.  */
          if ((info->flags & DF_TEXTREL) == 0)
          if ((info->flags & DF_TEXTREL) == 0)
            elf_link_hash_traverse (&htab->elf, readonly_dynrelocs,
            elf_link_hash_traverse (&htab->elf,
                                    (PTR) info);
                                    elf_i386_readonly_dynrelocs, info);
 
 
          if ((info->flags & DF_TEXTREL) != 0)
          if ((info->flags & DF_TEXTREL) != 0)
            {
            {
              if (!add_dynamic_entry (DT_TEXTREL, 0))
              if (!add_dynamic_entry (DT_TEXTREL, 0))
                return FALSE;
                return FALSE;
Line 2410... Line 2642...
          if (!(_bfd_generic_link_add_one_symbol
          if (!(_bfd_generic_link_add_one_symbol
                (info, output_bfd, "_TLS_MODULE_BASE_", BSF_LOCAL,
                (info, output_bfd, "_TLS_MODULE_BASE_", BSF_LOCAL,
                 tls_sec, 0, NULL, FALSE,
                 tls_sec, 0, NULL, FALSE,
                 bed->collect, &bh)))
                 bed->collect, &bh)))
            return FALSE;
            return FALSE;
 
 
 
          elf_i386_hash_table (info)->tls_module_base = bh;
 
 
          tlsbase = (struct elf_link_hash_entry *)bh;
          tlsbase = (struct elf_link_hash_entry *)bh;
          tlsbase->def_regular = 1;
          tlsbase->def_regular = 1;
          tlsbase->other = STV_HIDDEN;
          tlsbase->other = STV_HIDDEN;
          (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE);
          (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE);
        }
        }
Line 2454... Line 2689...
    hdr->sh_type = SHT_PROGBITS;
    hdr->sh_type = SHT_PROGBITS;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
 
/* _TLS_MODULE_BASE_ needs to be treated especially when linking
 
   executables.  Rather than setting it to the beginning of the TLS
 
   section, we have to set it to the end.    This function may be called
 
   multiple times, it is idempotent.  */
 
 
 
static void
 
elf_i386_set_tls_module_base (struct bfd_link_info *info)
 
{
 
  struct bfd_link_hash_entry *base;
 
 
 
  if (!info->executable)
 
    return;
 
 
 
  base = elf_i386_hash_table (info)->tls_module_base;
 
 
 
  if (!base)
 
    return;
 
 
 
  base->u.def.value = elf_hash_table (info)->tls_size;
 
}
 
 
/* Return the base VMA address which should be subtracted from real addresses
/* Return the base VMA address which should be subtracted from real addresses
   when resolving @dtpoff relocation.
   when resolving @dtpoff relocation.
   This is PT_TLS segment p_vaddr.  */
   This is PT_TLS segment p_vaddr.  */
 
 
static bfd_vma
static bfd_vma
dtpoff_base (struct bfd_link_info *info)
elf_i386_dtpoff_base (struct bfd_link_info *info)
{
{
  /* If tls_sec is NULL, we should have signalled an error already.  */
  /* If tls_sec is NULL, we should have signalled an error already.  */
  if (elf_hash_table (info)->tls_sec == NULL)
  if (elf_hash_table (info)->tls_sec == NULL)
    return 0;
    return 0;
  return elf_hash_table (info)->tls_sec->vma;
  return elf_hash_table (info)->tls_sec->vma;
Line 2471... Line 2727...
 
 
/* Return the relocation value for @tpoff relocation
/* Return the relocation value for @tpoff relocation
   if STT_TLS virtual address is ADDRESS.  */
   if STT_TLS virtual address is ADDRESS.  */
 
 
static bfd_vma
static bfd_vma
tpoff (struct bfd_link_info *info, bfd_vma address)
elf_i386_tpoff (struct bfd_link_info *info, bfd_vma address)
{
{
  struct elf_link_hash_table *htab = elf_hash_table (info);
  struct elf_link_hash_table *htab = elf_hash_table (info);
 
 
  /* If tls_sec is NULL, we should have signalled an error already.  */
  /* If tls_sec is NULL, we should have signalled an error already.  */
  if (htab->tls_sec == NULL)
  if (htab->tls_sec == NULL)
Line 2500... Line 2756...
  struct elf_link_hash_entry **sym_hashes;
  struct elf_link_hash_entry **sym_hashes;
  bfd_vma *local_got_offsets;
  bfd_vma *local_got_offsets;
  bfd_vma *local_tlsdesc_gotents;
  bfd_vma *local_tlsdesc_gotents;
  Elf_Internal_Rela *rel;
  Elf_Internal_Rela *rel;
  Elf_Internal_Rela *relend;
  Elf_Internal_Rela *relend;
 
  bfd_boolean is_vxworks_tls;
 
 
  BFD_ASSERT (is_i386_elf (input_bfd));
  BFD_ASSERT (is_i386_elf (input_bfd));
 
 
  htab = elf_i386_hash_table (info);
  htab = elf_i386_hash_table (info);
  symtab_hdr = &elf_symtab_hdr (input_bfd);
  symtab_hdr = &elf_symtab_hdr (input_bfd);
  sym_hashes = elf_sym_hashes (input_bfd);
  sym_hashes = elf_sym_hashes (input_bfd);
  local_got_offsets = elf_local_got_offsets (input_bfd);
  local_got_offsets = elf_local_got_offsets (input_bfd);
  local_tlsdesc_gotents = elf_i386_local_tlsdesc_gotent (input_bfd);
  local_tlsdesc_gotents = elf_i386_local_tlsdesc_gotent (input_bfd);
 
  /* We have to handle relocations in vxworks .tls_vars sections
 
     specially, because the dynamic loader is 'weird'.  */
 
  is_vxworks_tls = (htab->is_vxworks && info->shared
 
                    && !strcmp (input_section->output_section->name,
 
                                ".tls_vars"));
 
 
 
  elf_i386_set_tls_module_base (info);
 
 
  rel = relocs;
  rel = relocs;
  relend = relocs + input_section->reloc_count;
  relend = relocs + input_section->reloc_count;
  for (; rel < relend; rel++)
  for (; rel < relend; rel++)
    {
    {
Line 2535... Line 2799...
 
 
      if ((indx = r_type) >= R_386_standard
      if ((indx = r_type) >= R_386_standard
          && ((indx = r_type - R_386_ext_offset) - R_386_standard
          && ((indx = r_type - R_386_ext_offset) - R_386_standard
              >= R_386_ext - R_386_standard)
              >= R_386_ext - R_386_standard)
          && ((indx = r_type - R_386_tls_offset) - R_386_ext
          && ((indx = r_type - R_386_tls_offset) - R_386_ext
              >= R_386_tls - R_386_ext))
              >= R_386_irelative - R_386_ext))
        {
        {
          (*_bfd_error_handler)
          (*_bfd_error_handler)
            (_("%B: unrecognized relocation (0x%x) in section `%A'"),
            (_("%B: unrecognized relocation (0x%x) in section `%A'"),
             input_bfd, input_section, r_type);
             input_bfd, input_section, r_type);
          bfd_set_error (bfd_error_bad_value);
          bfd_set_error (bfd_error_bad_value);
Line 2627... Line 2891...
                    addend -= 4;
                    addend -= 4;
                  bfd_put_32 (input_bfd, addend, where);
                  bfd_put_32 (input_bfd, addend, where);
                  break;
                  break;
                }
                }
            }
            }
 
          else if (!info->relocatable
 
                   && ELF32_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
 
            {
 
              /* Relocate against local STT_GNU_IFUNC symbol.  */
 
              h = elf_i386_get_local_sym_hash (htab, input_bfd,
 
                                                   rel, FALSE);
 
              if (h == NULL)
 
                abort ();
 
 
 
              /* Set STT_GNU_IFUNC symbol value.  */
 
              h->root.u.def.value = sym->st_value;
 
              h->root.u.def.section = sec;
 
            }
        }
        }
      else
      else
        {
        {
          bfd_boolean warned;
          bfd_boolean warned;
 
 
Line 2652... Line 2929...
        }
        }
 
 
      if (info->relocatable)
      if (info->relocatable)
        continue;
        continue;
 
 
 
      /* Since STT_GNU_IFUNC symbol must go through PLT, we handle
 
         it here if it is defined in a non-shared object.  */
 
      if (h != NULL
 
          && h->type == STT_GNU_IFUNC
 
          && h->def_regular)
 
        {
 
          asection *plt, *gotplt, *base_got;
 
          bfd_vma plt_index;
 
          const char *name;
 
 
 
          if ((input_section->flags & SEC_ALLOC) == 0
 
              || h->plt.offset == (bfd_vma) -1)
 
            abort ();
 
 
 
          /* STT_GNU_IFUNC symbol must go through PLT.  */
 
          if (htab->elf.splt != NULL)
 
            {
 
              plt = htab->elf.splt;
 
              gotplt = htab->elf.sgotplt;
 
            }
 
          else
 
            {
 
              plt = htab->elf.iplt;
 
              gotplt = htab->elf.igotplt;
 
            }
 
 
 
          relocation = (plt->output_section->vma
 
                        + plt->output_offset + h->plt.offset);
 
 
 
          switch (r_type)
 
            {
 
            default:
 
              if (h->root.root.string)
 
                name = h->root.root.string;
 
              else
 
                name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
 
                                         NULL);
 
              (*_bfd_error_handler)
 
                (_("%B: relocation %s against STT_GNU_IFUNC "
 
                   "symbol `%s' isn't handled by %s"), input_bfd,
 
                 elf_howto_table[r_type].name,
 
                 name, __FUNCTION__);
 
              bfd_set_error (bfd_error_bad_value);
 
              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 to get 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
 
                      || info->executable)
 
                    {
 
                      /* 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 = htab->elf.irelifunc;
 
                  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;
 
 
 
            case R_386_GOT32:
 
              base_got = htab->elf.sgot;
 
              off = h->got.offset;
 
 
 
              if (base_got == NULL)
 
                abort ();
 
 
 
              if (off == (bfd_vma) -1)
 
                {
 
                  /* We can't use h->got.offset here to save state, or
 
                     even just remember the offset, as finish_dynamic_symbol
 
                     would use that as offset into .got.  */
 
 
 
                  if (htab->elf.splt != NULL)
 
                    {
 
                      plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;
 
                      off = (plt_index + 3) * 4;
 
                      base_got = htab->elf.sgotplt;
 
                    }
 
                  else
 
                    {
 
                      plt_index = h->plt.offset / PLT_ENTRY_SIZE;
 
                      off = plt_index * 4;
 
                      base_got = htab->elf.igotplt;
 
                    }
 
 
 
                  if (h->dynindx == -1
 
                      || h->forced_local
 
                      || info->symbolic)
 
                    {
 
                      /* This references the local defitionion.  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_32 (output_bfd, relocation,
 
                                      base_got->contents + off);
 
                          h->got.offset |= 1;
 
                        }
 
                    }
 
 
 
                  relocation = off;
 
 
 
                  /* Adjust for static executables.  */
 
                  if (htab->elf.splt == NULL)
 
                    relocation += gotplt->output_offset;
 
                }
 
              else
 
                {
 
                  relocation = (base_got->output_section->vma
 
                                + base_got->output_offset + off
 
                                - gotplt->output_section->vma
 
                                - gotplt->output_offset);
 
                  /* Adjust for static executables.  */
 
                  if (htab->elf.splt == NULL)
 
                    relocation += gotplt->output_offset;
 
                }
 
 
 
              goto do_relocation;
 
 
 
            case R_386_GOTOFF:
 
              relocation -= (gotplt->output_section->vma
 
                             + gotplt->output_offset);
 
              goto do_relocation;
 
            }
 
        }
 
 
      switch (r_type)
      switch (r_type)
        {
        {
        case R_386_GOT32:
        case R_386_GOT32:
          /* Relocation is to the entry for this symbol in the global
          /* Relocation is to the entry for this symbol in the global
             offset table.  */
             offset table.  */
          if (htab->sgot == NULL)
          if (htab->elf.sgot == NULL)
            abort ();
            abort ();
 
 
          if (h != NULL)
          if (h != NULL)
            {
            {
              bfd_boolean dyn;
              bfd_boolean dyn;
Line 2689... Line 3143...
                  if ((off & 1) != 0)
                  if ((off & 1) != 0)
                    off &= ~1;
                    off &= ~1;
                  else
                  else
                    {
                    {
                      bfd_put_32 (output_bfd, relocation,
                      bfd_put_32 (output_bfd, relocation,
                                  htab->sgot->contents + off);
                                  htab->elf.sgot->contents + off);
                      h->got.offset |= 1;
                      h->got.offset |= 1;
                    }
                    }
                }
                }
              else
              else
                unresolved_reloc = FALSE;
                unresolved_reloc = FALSE;
Line 2711... Line 3165...
              if ((off & 1) != 0)
              if ((off & 1) != 0)
                off &= ~1;
                off &= ~1;
              else
              else
                {
                {
                  bfd_put_32 (output_bfd, relocation,
                  bfd_put_32 (output_bfd, relocation,
                              htab->sgot->contents + off);
                              htab->elf.sgot->contents + off);
 
 
                  if (info->shared)
                  if (info->shared)
                    {
                    {
                      asection *s;
                      asection *s;
                      Elf_Internal_Rela outrel;
                      Elf_Internal_Rela outrel;
                      bfd_byte *loc;
                      bfd_byte *loc;
 
 
                      s = htab->srelgot;
                      s = htab->elf.srelgot;
                      if (s == NULL)
                      if (s == NULL)
                        abort ();
                        abort ();
 
 
                      outrel.r_offset = (htab->sgot->output_section->vma
                      outrel.r_offset = (htab->elf.sgot->output_section->vma
                                         + htab->sgot->output_offset
                                         + htab->elf.sgot->output_offset
                                         + off);
                                         + off);
                      outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
                      outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
                      loc = s->contents;
                      loc = s->contents;
                      loc += s->reloc_count++ * sizeof (Elf32_External_Rel);
                      loc += s->reloc_count++ * sizeof (Elf32_External_Rel);
                      bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
                      bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
Line 2739... Line 3193...
            }
            }
 
 
          if (off >= (bfd_vma) -2)
          if (off >= (bfd_vma) -2)
            abort ();
            abort ();
 
 
          relocation = htab->sgot->output_section->vma
          relocation = htab->elf.sgot->output_section->vma
                       + htab->sgot->output_offset + off
                       + htab->elf.sgot->output_offset + off
                       - htab->sgotplt->output_section->vma
                       - htab->elf.sgotplt->output_section->vma
                       - htab->sgotplt->output_offset;
                       - htab->elf.sgotplt->output_offset;
          break;
          break;
 
 
        case R_386_GOTOFF:
        case R_386_GOTOFF:
          /* Relocation is relative to the start of the global offset
          /* Relocation is relative to the start of the global offset
             table.  */
             table.  */
 
 
          /* Check to make sure it isn't a protected function symbol
          /* Check to make sure it isn't a protected function symbol
             for shared library since it may not be local when used
             for shared library since it may not be local when used
             as function address.  */
             as function address.  We also need to make sure that a
          if (info->shared
             symbol is defined locally.  */
              && !info->executable
          if (info->shared && h)
              && h
            {
              && h->def_regular
              if (!h->def_regular)
 
                {
 
                  const char *v;
 
 
 
                  switch (ELF_ST_VISIBILITY (h->other))
 
                    {
 
                    case STV_HIDDEN:
 
                      v = _("hidden symbol");
 
                      break;
 
                    case STV_INTERNAL:
 
                      v = _("internal symbol");
 
                      break;
 
                    case STV_PROTECTED:
 
                      v = _("protected symbol");
 
                      break;
 
                    default:
 
                      v = _("symbol");
 
                      break;
 
                    }
 
 
 
                  (*_bfd_error_handler)
 
                    (_("%B: relocation R_386_GOTOFF against undefined %s `%s' can not be used when making a shared object"),
 
                     input_bfd, v, h->root.root.string);
 
                  bfd_set_error (bfd_error_bad_value);
 
                  return FALSE;
 
                }
 
              else if (!info->executable
              && h->type == STT_FUNC
              && h->type == STT_FUNC
              && ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
              && ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
            {
            {
              (*_bfd_error_handler)
              (*_bfd_error_handler)
                (_("%B: relocation R_386_GOTOFF against protected function `%s' can not be used when making a shared object"),
                (_("%B: relocation R_386_GOTOFF against protected function `%s' can not be used when making a shared object"),
                 input_bfd, h->root.root.string);
                 input_bfd, h->root.root.string);
              bfd_set_error (bfd_error_bad_value);
              bfd_set_error (bfd_error_bad_value);
              return FALSE;
              return FALSE;
            }
            }
 
            }
 
 
          /* Note that sgot is not involved in this
          /* Note that sgot is not involved in this
             calculation.  We always want the start of .got.plt.  If we
             calculation.  We always want the start of .got.plt.  If we
             defined _GLOBAL_OFFSET_TABLE_ in a different way, as is
             defined _GLOBAL_OFFSET_TABLE_ in a different way, as is
             permitted by the ABI, we might have to change this
             permitted by the ABI, we might have to change this
             calculation.  */
             calculation.  */
          relocation -= htab->sgotplt->output_section->vma
          relocation -= htab->elf.sgotplt->output_section->vma
                        + htab->sgotplt->output_offset;
                        + htab->elf.sgotplt->output_offset;
          break;
          break;
 
 
        case R_386_GOTPC:
        case R_386_GOTPC:
          /* Use global offset table as symbol value.  */
          /* Use global offset table as symbol value.  */
          relocation = htab->sgotplt->output_section->vma
          relocation = htab->elf.sgotplt->output_section->vma
                       + htab->sgotplt->output_offset;
                       + htab->elf.sgotplt->output_offset;
          unresolved_reloc = FALSE;
          unresolved_reloc = FALSE;
          break;
          break;
 
 
        case R_386_PLT32:
        case R_386_PLT32:
          /* Relocation is to the entry for this symbol in the
          /* Relocation is to the entry for this symbol in the
Line 2792... Line 3273...
             without using the procedure linkage table.  */
             without using the procedure linkage table.  */
          if (h == NULL)
          if (h == NULL)
            break;
            break;
 
 
          if (h->plt.offset == (bfd_vma) -1
          if (h->plt.offset == (bfd_vma) -1
              || htab->splt == NULL)
              || htab->elf.splt == NULL)
            {
            {
              /* We didn't make a PLT entry for this symbol.  This
              /* We didn't make a PLT entry for this symbol.  This
                 happens when statically linking PIC code, or when
                 happens when statically linking PIC code, or when
                 using -Bsymbolic.  */
                 using -Bsymbolic.  */
              break;
              break;
            }
            }
 
 
          relocation = (htab->splt->output_section->vma
          relocation = (htab->elf.splt->output_section->vma
                        + htab->splt->output_offset
                        + htab->elf.splt->output_offset
                        + h->plt.offset);
                        + h->plt.offset);
          unresolved_reloc = FALSE;
          unresolved_reloc = FALSE;
          break;
          break;
 
 
        case R_386_32:
        case R_386_32:
        case R_386_PC32:
        case R_386_PC32:
          if ((input_section->flags & SEC_ALLOC) == 0)
          if ((input_section->flags & SEC_ALLOC) == 0
 
              || is_vxworks_tls)
            break;
            break;
 
 
          if ((info->shared
          if ((info->shared
               && (h == NULL
               && (h == NULL
                   || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                   || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
Line 2866... Line 3348...
                  relocate = TRUE;
                  relocate = TRUE;
                  outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
                  outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
                }
                }
 
 
              sreloc = elf_section_data (input_section)->sreloc;
              sreloc = elf_section_data (input_section)->sreloc;
              if (sreloc == NULL)
 
                abort ();
              BFD_ASSERT (sreloc != NULL && sreloc->contents != NULL);
 
 
              loc = sreloc->contents;
              loc = sreloc->contents;
              loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel);
              loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel);
 
 
              bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
              bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
 
 
              /* If this reloc is against an external symbol, we do
              /* If this reloc is against an external symbol, we do
                 not want to fiddle with the addend.  Otherwise, we
                 not want to fiddle with the addend.  Otherwise, we
                 need to include the symbol value so that it becomes
                 need to include the symbol value so that it becomes
Line 2883... Line 3366...
                continue;
                continue;
            }
            }
          break;
          break;
 
 
        case R_386_TLS_IE:
        case R_386_TLS_IE:
          if (info->shared)
          if (!info->executable)
            {
            {
              Elf_Internal_Rela outrel;
              Elf_Internal_Rela outrel;
              bfd_byte *loc;
              bfd_byte *loc;
              asection *sreloc;
              asection *sreloc;
 
 
Line 2919... Line 3402...
 
 
          if (! elf_i386_tls_transition (info, input_bfd,
          if (! elf_i386_tls_transition (info, input_bfd,
                                         input_section, contents,
                                         input_section, contents,
                                         symtab_hdr, sym_hashes,
                                         symtab_hdr, sym_hashes,
                                         &r_type, tls_type, rel,
                                         &r_type, tls_type, rel,
                                         relend, h))
                                         relend, h, r_symndx))
            return FALSE;
            return FALSE;
 
 
          if (r_type == R_386_TLS_LE_32)
          if (r_type == R_386_TLS_LE_32)
            {
            {
              BFD_ASSERT (! unresolved_reloc);
              BFD_ASSERT (! unresolved_reloc);
Line 2952... Line 3435...
                         (6 byte form of subl).  */
                         (6 byte form of subl).  */
                      memcpy (contents + rel->r_offset - 2,
                      memcpy (contents + rel->r_offset - 2,
                              "\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12);
                              "\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12);
                      roff = rel->r_offset + 6;
                      roff = rel->r_offset + 6;
                    }
                    }
                  bfd_put_32 (output_bfd, tpoff (info, relocation),
                  bfd_put_32 (output_bfd, elf_i386_tpoff (info, relocation),
                              contents + roff);
                              contents + roff);
                  /* Skip R_386_PC32/R_386_PLT32.  */
                  /* Skip R_386_PC32/R_386_PLT32.  */
                  rel++;
                  rel++;
                  continue;
                  continue;
                }
                }
Line 2979... Line 3462...
                  /* Now modify the instruction as appropriate.  */
                  /* Now modify the instruction as appropriate.  */
                  /* aoliva FIXME: remove the above and xor the byte
                  /* aoliva FIXME: remove the above and xor the byte
                     below with 0x86.  */
                     below with 0x86.  */
                  bfd_put_8 (output_bfd, val ^ 0x86,
                  bfd_put_8 (output_bfd, val ^ 0x86,
                             contents + roff - 1);
                             contents + roff - 1);
                  bfd_put_32 (output_bfd, -tpoff (info, relocation),
                  bfd_put_32 (output_bfd, -elf_i386_tpoff (info, relocation),
                              contents + roff);
                              contents + roff);
                  continue;
                  continue;
                }
                }
              else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL)
              else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL)
                {
                {
Line 3047... Line 3530...
                        default:
                        default:
                          BFD_FAIL ();
                          BFD_FAIL ();
                          break;
                          break;
                        }
                        }
                    }
                    }
                  bfd_put_32 (output_bfd, -tpoff (info, relocation),
                  bfd_put_32 (output_bfd, -elf_i386_tpoff (info, relocation),
                              contents + rel->r_offset);
                              contents + rel->r_offset);
                  continue;
                  continue;
                }
                }
              else
              else
                {
                {
Line 3093... Line 3576...
                                 contents + rel->r_offset - 1);
                                 contents + rel->r_offset - 1);
                    }
                    }
                  else
                  else
                    BFD_FAIL ();
                    BFD_FAIL ();
                  if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTIE)
                  if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTIE)
                    bfd_put_32 (output_bfd, -tpoff (info, relocation),
                    bfd_put_32 (output_bfd, -elf_i386_tpoff (info, relocation),
                                contents + rel->r_offset);
                                contents + rel->r_offset);
                  else
                  else
                    bfd_put_32 (output_bfd, tpoff (info, relocation),
                    bfd_put_32 (output_bfd, elf_i386_tpoff (info, relocation),
                                contents + rel->r_offset);
                                contents + rel->r_offset);
                  continue;
                  continue;
                }
                }
            }
            }
 
 
          if (htab->sgot == NULL)
          if (htab->elf.sgot == NULL)
            abort ();
            abort ();
 
 
          if (h != NULL)
          if (h != NULL)
            {
            {
              off = h->got.offset;
              off = h->got.offset;
Line 3128... Line 3611...
              Elf_Internal_Rela outrel;
              Elf_Internal_Rela outrel;
              bfd_byte *loc;
              bfd_byte *loc;
              int dr_type, indx;
              int dr_type, indx;
              asection *sreloc;
              asection *sreloc;
 
 
              if (htab->srelgot == NULL)
              if (htab->elf.srelgot == NULL)
                abort ();
                abort ();
 
 
              indx = h && h->dynindx != -1 ? h->dynindx : 0;
              indx = h && h->dynindx != -1 ? h->dynindx : 0;
 
 
              if (GOT_TLS_GDESC_P (tls_type))
              if (GOT_TLS_GDESC_P (tls_type))
                {
                {
                  outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_DESC);
                  outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_DESC);
                  BFD_ASSERT (htab->sgotplt_jump_table_size + offplt + 8
                  BFD_ASSERT (htab->sgotplt_jump_table_size + offplt + 8
                              <= htab->sgotplt->size);
                              <= htab->elf.sgotplt->size);
                  outrel.r_offset = (htab->sgotplt->output_section->vma
                  outrel.r_offset = (htab->elf.sgotplt->output_section->vma
                                     + htab->sgotplt->output_offset
                                     + htab->elf.sgotplt->output_offset
                                     + offplt
                                     + offplt
                                     + htab->sgotplt_jump_table_size);
                                     + htab->sgotplt_jump_table_size);
                  sreloc = htab->srelplt;
                  sreloc = htab->elf.srelplt;
                  loc = sreloc->contents;
                  loc = sreloc->contents;
                  loc += (htab->next_tls_desc_index++
                  loc += (htab->next_tls_desc_index++
                          * sizeof (Elf32_External_Rel));
                          * sizeof (Elf32_External_Rel));
                  BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
                  BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
                              <= sreloc->contents + sreloc->size);
                              <= sreloc->contents + sreloc->size);
                  bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
                  bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
                  if (indx == 0)
                  if (indx == 0)
                    {
                    {
                      BFD_ASSERT (! unresolved_reloc);
                      BFD_ASSERT (! unresolved_reloc);
                      bfd_put_32 (output_bfd,
                      bfd_put_32 (output_bfd,
                                  relocation - dtpoff_base (info),
                                  relocation - elf_i386_dtpoff_base (info),
                                  htab->sgotplt->contents + offplt
                                  htab->elf.sgotplt->contents + offplt
                                  + htab->sgotplt_jump_table_size + 4);
                                  + htab->sgotplt_jump_table_size + 4);
                    }
                    }
                  else
                  else
                    {
                    {
                      bfd_put_32 (output_bfd, 0,
                      bfd_put_32 (output_bfd, 0,
                                  htab->sgotplt->contents + offplt
                                  htab->elf.sgotplt->contents + offplt
                                  + htab->sgotplt_jump_table_size + 4);
                                  + htab->sgotplt_jump_table_size + 4);
                    }
                    }
                }
                }
 
 
              sreloc = htab->srelgot;
              sreloc = htab->elf.srelgot;
 
 
              outrel.r_offset = (htab->sgot->output_section->vma
              outrel.r_offset = (htab->elf.sgot->output_section->vma
                                 + htab->sgot->output_offset + off);
                                 + htab->elf.sgot->output_offset + off);
 
 
              if (GOT_TLS_GD_P (tls_type))
              if (GOT_TLS_GD_P (tls_type))
                dr_type = R_386_TLS_DTPMOD32;
                dr_type = R_386_TLS_DTPMOD32;
              else if (GOT_TLS_GDESC_P (tls_type))
              else if (GOT_TLS_GDESC_P (tls_type))
                goto dr_done;
                goto dr_done;
Line 3180... Line 3663...
                dr_type = R_386_TLS_TPOFF;
                dr_type = R_386_TLS_TPOFF;
              else
              else
                dr_type = R_386_TLS_TPOFF32;
                dr_type = R_386_TLS_TPOFF32;
 
 
              if (dr_type == R_386_TLS_TPOFF && indx == 0)
              if (dr_type == R_386_TLS_TPOFF && indx == 0)
                bfd_put_32 (output_bfd, relocation - dtpoff_base (info),
                bfd_put_32 (output_bfd,
                            htab->sgot->contents + off);
                            relocation - elf_i386_dtpoff_base (info),
 
                            htab->elf.sgot->contents + off);
              else if (dr_type == R_386_TLS_TPOFF32 && indx == 0)
              else if (dr_type == R_386_TLS_TPOFF32 && indx == 0)
                bfd_put_32 (output_bfd, dtpoff_base (info) - relocation,
                bfd_put_32 (output_bfd,
                            htab->sgot->contents + off);
                            elf_i386_dtpoff_base (info) - relocation,
 
                            htab->elf.sgot->contents + off);
              else if (dr_type != R_386_TLS_DESC)
              else if (dr_type != R_386_TLS_DESC)
                bfd_put_32 (output_bfd, 0,
                bfd_put_32 (output_bfd, 0,
                            htab->sgot->contents + off);
                            htab->elf.sgot->contents + off);
              outrel.r_info = ELF32_R_INFO (indx, dr_type);
              outrel.r_info = ELF32_R_INFO (indx, dr_type);
 
 
              loc = sreloc->contents;
              loc = sreloc->contents;
              loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel);
              loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel);
              BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
              BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
Line 3202... Line 3687...
                {
                {
                  if (indx == 0)
                  if (indx == 0)
                    {
                    {
                      BFD_ASSERT (! unresolved_reloc);
                      BFD_ASSERT (! unresolved_reloc);
                      bfd_put_32 (output_bfd,
                      bfd_put_32 (output_bfd,
                                  relocation - dtpoff_base (info),
                                  relocation - elf_i386_dtpoff_base (info),
                                  htab->sgot->contents + off + 4);
                                  htab->elf.sgot->contents + off + 4);
                    }
                    }
                  else
                  else
                    {
                    {
                      bfd_put_32 (output_bfd, 0,
                      bfd_put_32 (output_bfd, 0,
                                  htab->sgot->contents + off + 4);
                                  htab->elf.sgot->contents + off + 4);
                      outrel.r_info = ELF32_R_INFO (indx,
                      outrel.r_info = ELF32_R_INFO (indx,
                                                    R_386_TLS_DTPOFF32);
                                                    R_386_TLS_DTPOFF32);
                      outrel.r_offset += 4;
                      outrel.r_offset += 4;
                      sreloc->reloc_count++;
                      sreloc->reloc_count++;
                      loc += sizeof (Elf32_External_Rel);
                      loc += sizeof (Elf32_External_Rel);
Line 3222... Line 3707...
                    }
                    }
                }
                }
              else if (tls_type == GOT_TLS_IE_BOTH)
              else if (tls_type == GOT_TLS_IE_BOTH)
                {
                {
                  bfd_put_32 (output_bfd,
                  bfd_put_32 (output_bfd,
                              indx == 0 ? relocation - dtpoff_base (info) : 0,
                              (indx == 0
                              htab->sgot->contents + off + 4);
                               ? relocation - elf_i386_dtpoff_base (info)
 
                               : 0),
 
                              htab->elf.sgot->contents + off + 4);
                  outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_TPOFF);
                  outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_TPOFF);
                  outrel.r_offset += 4;
                  outrel.r_offset += 4;
                  sreloc->reloc_count++;
                  sreloc->reloc_count++;
                  loc += sizeof (Elf32_External_Rel);
                  loc += sizeof (Elf32_External_Rel);
                  bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
                  bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
Line 3249... Line 3736...
              relocation = htab->sgotplt_jump_table_size + offplt;
              relocation = htab->sgotplt_jump_table_size + offplt;
              unresolved_reloc = FALSE;
              unresolved_reloc = FALSE;
            }
            }
          else if (r_type == ELF32_R_TYPE (rel->r_info))
          else if (r_type == ELF32_R_TYPE (rel->r_info))
            {
            {
              bfd_vma g_o_t = htab->sgotplt->output_section->vma
              bfd_vma g_o_t = htab->elf.sgotplt->output_section->vma
                              + htab->sgotplt->output_offset;
                              + htab->elf.sgotplt->output_offset;
              relocation = htab->sgot->output_section->vma
              relocation = htab->elf.sgot->output_section->vma
                + htab->sgot->output_offset + off - g_o_t;
                + htab->elf.sgot->output_offset + off - g_o_t;
              if ((r_type == R_386_TLS_IE || r_type == R_386_TLS_GOTIE)
              if ((r_type == R_386_TLS_IE || r_type == R_386_TLS_GOTIE)
                  && tls_type == GOT_TLS_IE_BOTH)
                  && tls_type == GOT_TLS_IE_BOTH)
                relocation += 4;
                relocation += 4;
              if (r_type == R_386_TLS_IE)
              if (r_type == R_386_TLS_IE)
                relocation += g_o_t;
                relocation += g_o_t;
Line 3294... Line 3781...
                 into:
                 into:
                 addl $foo@gotntpoff(%reg), %eax.  */
                 addl $foo@gotntpoff(%reg), %eax.  */
              if (tls_type == GOT_TLS_IE_POS)
              if (tls_type == GOT_TLS_IE_POS)
                contents[roff + 6] = 0x03;
                contents[roff + 6] = 0x03;
              bfd_put_32 (output_bfd,
              bfd_put_32 (output_bfd,
                          htab->sgot->output_section->vma
                          htab->elf.sgot->output_section->vma
                          + htab->sgot->output_offset + off
                          + htab->elf.sgot->output_offset + off
                          - htab->sgotplt->output_section->vma
                          - htab->elf.sgotplt->output_section->vma
                          - htab->sgotplt->output_offset,
                          - htab->elf.sgotplt->output_offset,
                          contents + roff + 8);
                          contents + roff + 8);
              /* Skip R_386_PLT32.  */
              /* Skip R_386_PLT32.  */
              rel++;
              rel++;
              continue;
              continue;
            }
            }
Line 3335... Line 3822...
 
 
              if (tls_type == GOT_TLS_IE_BOTH)
              if (tls_type == GOT_TLS_IE_BOTH)
                off += 4;
                off += 4;
 
 
              bfd_put_32 (output_bfd,
              bfd_put_32 (output_bfd,
                          htab->sgot->output_section->vma
                          htab->elf.sgot->output_section->vma
                          + htab->sgot->output_offset + off
                          + htab->elf.sgot->output_offset + off
                          - htab->sgotplt->output_section->vma
                          - htab->elf.sgotplt->output_section->vma
                          - htab->sgotplt->output_offset,
                          - htab->elf.sgotplt->output_offset,
                          contents + roff);
                          contents + roff);
              continue;
              continue;
            }
            }
          else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL)
          else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL)
            {
            {
Line 3384... Line 3871...
        case R_386_TLS_LDM:
        case R_386_TLS_LDM:
          if (! elf_i386_tls_transition (info, input_bfd,
          if (! elf_i386_tls_transition (info, input_bfd,
                                         input_section, contents,
                                         input_section, contents,
                                         symtab_hdr, sym_hashes,
                                         symtab_hdr, sym_hashes,
                                         &r_type, GOT_UNKNOWN, rel,
                                         &r_type, GOT_UNKNOWN, rel,
                                         relend, h))
                                         relend, h, r_symndx))
            return FALSE;
            return FALSE;
 
 
          if (r_type != R_386_TLS_LDM)
          if (r_type != R_386_TLS_LDM)
            {
            {
              /* LD->LE transition:
              /* LD->LE transition:
Line 3401... Line 3888...
              /* Skip R_386_PC32/R_386_PLT32.  */
              /* Skip R_386_PC32/R_386_PLT32.  */
              rel++;
              rel++;
              continue;
              continue;
            }
            }
 
 
          if (htab->sgot == NULL)
          if (htab->elf.sgot == NULL)
            abort ();
            abort ();
 
 
          off = htab->tls_ldm_got.offset;
          off = htab->tls_ldm_got.offset;
          if (off & 1)
          if (off & 1)
            off &= ~1;
            off &= ~1;
          else
          else
            {
            {
              Elf_Internal_Rela outrel;
              Elf_Internal_Rela outrel;
              bfd_byte *loc;
              bfd_byte *loc;
 
 
              if (htab->srelgot == NULL)
              if (htab->elf.srelgot == NULL)
                abort ();
                abort ();
 
 
              outrel.r_offset = (htab->sgot->output_section->vma
              outrel.r_offset = (htab->elf.sgot->output_section->vma
                                 + htab->sgot->output_offset + off);
                                 + htab->elf.sgot->output_offset + off);
 
 
              bfd_put_32 (output_bfd, 0,
              bfd_put_32 (output_bfd, 0,
                          htab->sgot->contents + off);
                          htab->elf.sgot->contents + off);
              bfd_put_32 (output_bfd, 0,
              bfd_put_32 (output_bfd, 0,
                          htab->sgot->contents + off + 4);
                          htab->elf.sgot->contents + off + 4);
              outrel.r_info = ELF32_R_INFO (0, R_386_TLS_DTPMOD32);
              outrel.r_info = ELF32_R_INFO (0, R_386_TLS_DTPMOD32);
              loc = htab->srelgot->contents;
              loc = htab->elf.srelgot->contents;
              loc += htab->srelgot->reloc_count++ * sizeof (Elf32_External_Rel);
              loc += htab->elf.srelgot->reloc_count++ * sizeof (Elf32_External_Rel);
              bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
              bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
              htab->tls_ldm_got.offset |= 1;
              htab->tls_ldm_got.offset |= 1;
            }
            }
          relocation = htab->sgot->output_section->vma
          relocation = htab->elf.sgot->output_section->vma
                       + htab->sgot->output_offset + off
                       + htab->elf.sgot->output_offset + off
                       - htab->sgotplt->output_section->vma
                       - htab->elf.sgotplt->output_section->vma
                       - htab->sgotplt->output_offset;
                       - htab->elf.sgotplt->output_offset;
          unresolved_reloc = FALSE;
          unresolved_reloc = FALSE;
          break;
          break;
 
 
        case R_386_TLS_LDO_32:
        case R_386_TLS_LDO_32:
          if (info->shared || (input_section->flags & SEC_CODE) == 0)
          if (info->shared || (input_section->flags & SEC_CODE) == 0)
            relocation -= dtpoff_base (info);
            relocation -= elf_i386_dtpoff_base (info);
          else
          else
            /* When converting LDO to LE, we must negate.  */
            /* When converting LDO to LE, we must negate.  */
            relocation = -tpoff (info, relocation);
            relocation = -elf_i386_tpoff (info, relocation);
          break;
          break;
 
 
        case R_386_TLS_LE_32:
        case R_386_TLS_LE_32:
        case R_386_TLS_LE:
        case R_386_TLS_LE:
          if (info->shared)
          if (!info->executable)
            {
            {
              Elf_Internal_Rela outrel;
              Elf_Internal_Rela outrel;
              asection *sreloc;
              asection *sreloc;
              bfd_byte *loc;
              bfd_byte *loc;
              int indx;
              int indx;
Line 3472... Line 3959...
              loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel);
              loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel);
              bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
              bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
              if (indx)
              if (indx)
                continue;
                continue;
              else if (r_type == R_386_TLS_LE_32)
              else if (r_type == R_386_TLS_LE_32)
                relocation = dtpoff_base (info) - relocation;
                relocation = elf_i386_dtpoff_base (info) - relocation;
              else
              else
                relocation -= dtpoff_base (info);
                relocation -= elf_i386_dtpoff_base (info);
            }
            }
          else if (r_type == R_386_TLS_LE_32)
          else if (r_type == R_386_TLS_LE_32)
            relocation = tpoff (info, relocation);
            relocation = elf_i386_tpoff (info, relocation);
          else
          else
            relocation = -tpoff (info, relocation);
            relocation = -elf_i386_tpoff (info, relocation);
          break;
          break;
 
 
        default:
        default:
          break;
          break;
        }
        }
Line 3503... Line 3990...
             howto->name,
             howto->name,
             h->root.root.string);
             h->root.root.string);
          return FALSE;
          return FALSE;
        }
        }
 
 
 
do_relocation:
      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
      r = _bfd_final_link_relocate (howto, input_bfd, input_section,
                                    contents, rel->r_offset,
                                    contents, rel->r_offset,
                                    relocation, 0);
                                    relocation, 0);
 
 
      if (r != bfd_reloc_ok)
      if (r != bfd_reloc_ok)
Line 3565... Line 4053...
    {
    {
      bfd_vma plt_index;
      bfd_vma plt_index;
      bfd_vma got_offset;
      bfd_vma got_offset;
      Elf_Internal_Rela rel;
      Elf_Internal_Rela rel;
      bfd_byte *loc;
      bfd_byte *loc;
 
      asection *plt, *gotplt, *relplt;
 
 
 
      /* When building a static executable, use .iplt, .igot.plt and
 
         .rel.iplt sections for STT_GNU_IFUNC symbols.  */
 
      if (htab->elf.splt != NULL)
 
        {
 
          plt = htab->elf.splt;
 
          gotplt = htab->elf.sgotplt;
 
          relplt = htab->elf.srelplt;
 
        }
 
      else
 
        {
 
          plt = htab->elf.iplt;
 
          gotplt = htab->elf.igotplt;
 
          relplt = htab->elf.irelplt;
 
        }
 
 
      /* This symbol has an entry in the procedure linkage table.  Set
      /* This symbol has an entry in the procedure linkage table.  Set
         it up.  */
         it up.  */
 
 
      if (h->dynindx == -1
      if ((h->dynindx == -1
          || htab->splt == NULL
           && !((h->forced_local || info->executable)
          || htab->sgotplt == NULL
                && h->def_regular
          || htab->srelplt == NULL)
                && h->type == STT_GNU_IFUNC))
 
          || plt == NULL
 
          || gotplt == NULL
 
          || relplt == NULL)
        abort ();
        abort ();
 
 
      /* Get the index in the procedure linkage table which
      /* Get the index in the procedure linkage table which
         corresponds to this symbol.  This is the index of this symbol
         corresponds to this symbol.  This is the index of this symbol
         in all the symbols for which we are making plt entries.  The
         in all the symbols for which we are making plt entries.  The
         first entry in the procedure linkage table is reserved.  */
         first entry in the procedure linkage table is reserved.
      plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;
 
 
 
      /* Get the offset into the .got table of the entry that
         Get the offset into the .got table of the entry that
         corresponds to this function.  Each .got entry is 4 bytes.
         corresponds to this function.  Each .got entry is 4 bytes.
         The first three are reserved.  */
         The first three are reserved.
 
 
 
         For static executables, we don't reserve anything.  */
 
 
 
      if (plt == htab->elf.splt)
 
        {
 
          plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;
      got_offset = (plt_index + 3) * 4;
      got_offset = (plt_index + 3) * 4;
 
        }
 
      else
 
        {
 
          plt_index = h->plt.offset / PLT_ENTRY_SIZE;
 
          got_offset = plt_index * 4;
 
        }
 
 
      /* Fill in the entry in the procedure linkage table.  */
      /* Fill in the entry in the procedure linkage table.  */
      if (! info->shared)
      if (! info->shared)
        {
        {
          memcpy (htab->splt->contents + h->plt.offset, elf_i386_plt_entry,
          memcpy (plt->contents + h->plt.offset, elf_i386_plt_entry,
                  PLT_ENTRY_SIZE);
                  PLT_ENTRY_SIZE);
          bfd_put_32 (output_bfd,
          bfd_put_32 (output_bfd,
                      (htab->sgotplt->output_section->vma
                      (gotplt->output_section->vma
                       + htab->sgotplt->output_offset
                       + gotplt->output_offset
                       + got_offset),
                       + got_offset),
                      htab->splt->contents + h->plt.offset + 2);
                      plt->contents + h->plt.offset + 2);
 
 
          if (htab->is_vxworks)
          if (htab->is_vxworks)
            {
            {
              int s, k, reloc_index;
              int s, k, reloc_index;
 
 
Line 3617... Line 4135...
                 the other PLT slots. */
                 the other PLT slots. */
              reloc_index = k + s * PLT_NON_JUMP_SLOT_RELOCS;
              reloc_index = k + s * PLT_NON_JUMP_SLOT_RELOCS;
              loc = (htab->srelplt2->contents + reloc_index
              loc = (htab->srelplt2->contents + reloc_index
                     * sizeof (Elf32_External_Rel));
                     * sizeof (Elf32_External_Rel));
 
 
              rel.r_offset = (htab->splt->output_section->vma
              rel.r_offset = (htab->elf.splt->output_section->vma
                              + htab->splt->output_offset
                              + htab->elf.splt->output_offset
                              + h->plt.offset + 2),
                              + h->plt.offset + 2),
              rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32);
              rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32);
              bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
              bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
 
 
              /* Create the R_386_32 relocation referencing the beginning of
              /* Create the R_386_32 relocation referencing the beginning of
                 the PLT for this GOT entry.  */
                 the PLT for this GOT entry.  */
              rel.r_offset = (htab->sgotplt->output_section->vma
              rel.r_offset = (htab->elf.sgotplt->output_section->vma
                              + htab->sgotplt->output_offset
                              + htab->elf.sgotplt->output_offset
                              + got_offset);
                              + got_offset);
              rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx, R_386_32);
              rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx, R_386_32);
              bfd_elf32_swap_reloc_out (output_bfd, &rel,
              bfd_elf32_swap_reloc_out (output_bfd, &rel,
              loc + sizeof (Elf32_External_Rel));
              loc + sizeof (Elf32_External_Rel));
            }
            }
        }
        }
      else
      else
        {
        {
          memcpy (htab->splt->contents + h->plt.offset, elf_i386_pic_plt_entry,
          memcpy (plt->contents + h->plt.offset, elf_i386_pic_plt_entry,
                  PLT_ENTRY_SIZE);
                  PLT_ENTRY_SIZE);
          bfd_put_32 (output_bfd, got_offset,
          bfd_put_32 (output_bfd, got_offset,
                      htab->splt->contents + h->plt.offset + 2);
                      plt->contents + h->plt.offset + 2);
        }
        }
 
 
 
      /* Don't fill PLT entry for static executables.  */
 
      if (plt == htab->elf.splt)
 
        {
      bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rel),
      bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rel),
                  htab->splt->contents + h->plt.offset + 7);
                      plt->contents + h->plt.offset + 7);
      bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE),
      bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE),
                  htab->splt->contents + h->plt.offset + 12);
                      plt->contents + h->plt.offset + 12);
 
        }
 
 
      /* Fill in the entry in the global offset table.  */
      /* Fill in the entry in the global offset table.  */
      bfd_put_32 (output_bfd,
      bfd_put_32 (output_bfd,
                  (htab->splt->output_section->vma
                  (plt->output_section->vma
                   + htab->splt->output_offset
                   + plt->output_offset
                   + h->plt.offset
                   + h->plt.offset
                   + 6),
                   + 6),
                  htab->sgotplt->contents + got_offset);
                  gotplt->contents + got_offset);
 
 
      /* Fill in the entry in the .rel.plt section.  */
      /* Fill in the entry in the .rel.plt section.  */
      rel.r_offset = (htab->sgotplt->output_section->vma
      rel.r_offset = (gotplt->output_section->vma
                      + htab->sgotplt->output_offset
                      + gotplt->output_offset
                      + got_offset);
                      + got_offset);
 
      if (h->dynindx == -1
 
          || ((info->executable
 
               || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
 
              && h->def_regular
 
               && h->type == STT_GNU_IFUNC))
 
        {
 
          /* If an STT_GNU_IFUNC symbol is locally defined, generate
 
             R_386_IRELATIVE instead of R_386_JUMP_SLOT.  Store addend
 
             in the .got.plt section.  */
 
          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),
 
                      gotplt->contents + got_offset);
 
          rel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
 
        }
 
      else
      rel.r_info = ELF32_R_INFO (h->dynindx, R_386_JUMP_SLOT);
      rel.r_info = ELF32_R_INFO (h->dynindx, R_386_JUMP_SLOT);
      loc = htab->srelplt->contents + plt_index * sizeof (Elf32_External_Rel);
      loc = relplt->contents + plt_index * sizeof (Elf32_External_Rel);
      bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
      bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
 
 
      if (!h->def_regular)
      if (!h->def_regular)
        {
        {
          /* Mark the symbol as undefined, rather than as defined in
          /* Mark the symbol as undefined, rather than as defined in
Line 3688... Line 4227...
      bfd_byte *loc;
      bfd_byte *loc;
 
 
      /* This symbol has an entry in the global offset table.  Set it
      /* This symbol has an entry in the global offset table.  Set it
         up.  */
         up.  */
 
 
      if (htab->sgot == NULL || htab->srelgot == NULL)
      if (htab->elf.sgot == NULL || htab->elf.srelgot == NULL)
        abort ();
        abort ();
 
 
      rel.r_offset = (htab->sgot->output_section->vma
      rel.r_offset = (htab->elf.sgot->output_section->vma
                      + htab->sgot->output_offset
                      + htab->elf.sgot->output_offset
                      + (h->got.offset & ~(bfd_vma) 1));
                      + (h->got.offset & ~(bfd_vma) 1));
 
 
      /* If this is a static link, or it is a -Bsymbolic link and the
      /* If this is a static link, or it is a -Bsymbolic link and the
         symbol is defined locally or was forced to be local because
         symbol is defined locally or was forced to be local because
         of a version file, we just want to emit a RELATIVE reloc.
         of a version file, we just want to emit a RELATIVE reloc.
         The entry in the global offset table will already have been
         The entry in the global offset table will already have been
         initialized in the relocate_section function.  */
         initialized in the relocate_section function.  */
      if (info->shared
      if (h->def_regular
 
          && h->type == STT_GNU_IFUNC)
 
        {
 
          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->elf.splt ? htab->elf.splt : htab->elf.iplt;
 
              bfd_put_32 (output_bfd,
 
                          (plt->output_section->vma
 
                           + plt->output_offset + h->plt.offset),
 
                          htab->elf.sgot->contents + h->got.offset);
 
              return TRUE;
 
            }
 
        }
 
      else if (info->shared
          && SYMBOL_REFERENCES_LOCAL (info, h))
          && SYMBOL_REFERENCES_LOCAL (info, h))
        {
        {
          BFD_ASSERT((h->got.offset & 1) != 0);
          BFD_ASSERT((h->got.offset & 1) != 0);
          rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
          rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
        }
        }
      else
      else
        {
        {
          BFD_ASSERT((h->got.offset & 1) == 0);
          BFD_ASSERT((h->got.offset & 1) == 0);
 
do_glob_dat:
          bfd_put_32 (output_bfd, (bfd_vma) 0,
          bfd_put_32 (output_bfd, (bfd_vma) 0,
                      htab->sgot->contents + h->got.offset);
                      htab->elf.sgot->contents + h->got.offset);
          rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT);
          rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT);
        }
        }
 
 
      loc = htab->srelgot->contents;
      loc = htab->elf.srelgot->contents;
      loc += htab->srelgot->reloc_count++ * sizeof (Elf32_External_Rel);
      loc += htab->elf.srelgot->reloc_count++ * sizeof (Elf32_External_Rel);
      bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
      bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
    }
    }
 
 
  if (h->needs_copy)
  if (h->needs_copy)
    {
    {
Line 3741... Line 4305...
      loc = htab->srelbss->contents;
      loc = htab->srelbss->contents;
      loc += htab->srelbss->reloc_count++ * sizeof (Elf32_External_Rel);
      loc += htab->srelbss->reloc_count++ * sizeof (Elf32_External_Rel);
      bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
      bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
    }
    }
 
 
  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.
  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  SYM may
 
     be NULL for local symbols.
 
 
     On VxWorks, the _GLOBAL_OFFSET_TABLE_ symbol is not absolute: it
     On VxWorks, the _GLOBAL_OFFSET_TABLE_ symbol is not absolute: it
     is relative to the ".got" section.  */
     is relative to the ".got" section.  */
  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
  if (sym != NULL
      || (!htab->is_vxworks && h == htab->elf.hgot))
      && (strcmp (h->root.root.string, "_DYNAMIC") == 0
 
          || (!htab->is_vxworks && h == htab->elf.hgot)))
    sym->st_shndx = SHN_ABS;
    sym->st_shndx = SHN_ABS;
 
 
  return TRUE;
  return TRUE;
}
}
 
 
 
/* Finish up local dynamic symbol handling.  We set the contents of
 
   various dynamic sections here.  */
 
 
 
static bfd_boolean
 
elf_i386_finish_local_dynamic_symbol (void **slot, void *inf)
 
{
 
  struct elf_link_hash_entry *h
 
    = (struct elf_link_hash_entry *) *slot;
 
  struct bfd_link_info *info
 
    = (struct bfd_link_info *) inf;
 
 
 
  return elf_i386_finish_dynamic_symbol (info->output_bfd, info,
 
                                         h, NULL);
 
}
 
 
/* Used to decide how to sort relocs in an optimal manner for the
/* Used to decide how to sort relocs in an optimal manner for the
   dynamic linker, before writing them out.  */
   dynamic linker, before writing them out.  */
 
 
static enum elf_reloc_type_class
static enum elf_reloc_type_class
elf_i386_reloc_type_class (const Elf_Internal_Rela *rela)
elf_i386_reloc_type_class (const Elf_Internal_Rela *rela)
Line 3788... Line 4370...
 
 
  if (htab->elf.dynamic_sections_created)
  if (htab->elf.dynamic_sections_created)
    {
    {
      Elf32_External_Dyn *dyncon, *dynconend;
      Elf32_External_Dyn *dyncon, *dynconend;
 
 
      if (sdyn == NULL || htab->sgot == NULL)
      if (sdyn == NULL || htab->elf.sgot == NULL)
        abort ();
        abort ();
 
 
      dyncon = (Elf32_External_Dyn *) sdyn->contents;
      dyncon = (Elf32_External_Dyn *) sdyn->contents;
      dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
      dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
      for (; dyncon < dynconend; dyncon++)
      for (; dyncon < dynconend; dyncon++)
Line 3809... Line 4391...
                  && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
                  && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
                break;
                break;
              continue;
              continue;
 
 
            case DT_PLTGOT:
            case DT_PLTGOT:
              s = htab->sgotplt;
              s = htab->elf.sgotplt;
              dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              break;
              break;
 
 
            case DT_JMPREL:
            case DT_JMPREL:
              s = htab->srelplt;
              s = htab->elf.srelplt;
              dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
              break;
              break;
 
 
            case DT_PLTRELSZ:
            case DT_PLTRELSZ:
              s = htab->srelplt;
              s = htab->elf.srelplt;
              dyn.d_un.d_val = s->size;
              dyn.d_un.d_val = s->size;
              break;
              break;
 
 
            case DT_RELSZ:
            case DT_RELSZ:
              /* My reading of the SVR4 ABI indicates that the
              /* My reading of the SVR4 ABI indicates that the
                 procedure linkage table relocs (DT_JMPREL) should be
                 procedure linkage table relocs (DT_JMPREL) should be
                 included in the overall relocs (DT_REL).  This is
                 included in the overall relocs (DT_REL).  This is
                 what Solaris does.  However, UnixWare can not handle
                 what Solaris does.  However, UnixWare can not handle
                 that case.  Therefore, we override the DT_RELSZ entry
                 that case.  Therefore, we override the DT_RELSZ entry
                 here to make it not include the JMPREL relocs.  */
                 here to make it not include the JMPREL relocs.  */
              s = htab->srelplt;
              s = htab->elf.srelplt;
              if (s == NULL)
              if (s == NULL)
                continue;
                continue;
              dyn.d_un.d_val -= s->size;
              dyn.d_un.d_val -= s->size;
              break;
              break;
 
 
            case DT_REL:
            case DT_REL:
              /* We may not be using the standard ELF linker script.
              /* We may not be using the standard ELF linker script.
                 If .rel.plt is the first .rel section, we adjust
                 If .rel.plt is the first .rel section, we adjust
                 DT_REL to not include it.  */
                 DT_REL to not include it.  */
              s = htab->srelplt;
              s = htab->elf.srelplt;
              if (s == NULL)
              if (s == NULL)
                continue;
                continue;
              if (dyn.d_un.d_ptr != s->output_section->vma + s->output_offset)
              if (dyn.d_un.d_ptr != s->output_section->vma + s->output_offset)
                continue;
                continue;
              dyn.d_un.d_ptr += s->size;
              dyn.d_un.d_ptr += s->size;
Line 3853... Line 4435...
 
 
          bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
          bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
        }
        }
 
 
      /* Fill in the first entry in the procedure linkage table.  */
      /* Fill in the first entry in the procedure linkage table.  */
      if (htab->splt && htab->splt->size > 0)
      if (htab->elf.splt && htab->elf.splt->size > 0)
        {
        {
          if (info->shared)
          if (info->shared)
            {
            {
              memcpy (htab->splt->contents, elf_i386_pic_plt0_entry,
              memcpy (htab->elf.splt->contents, elf_i386_pic_plt0_entry,
                      sizeof (elf_i386_pic_plt0_entry));
                      sizeof (elf_i386_pic_plt0_entry));
              memset (htab->splt->contents + sizeof (elf_i386_pic_plt0_entry),
              memset (htab->elf.splt->contents + sizeof (elf_i386_pic_plt0_entry),
                      htab->plt0_pad_byte,
                      htab->plt0_pad_byte,
                      PLT_ENTRY_SIZE - sizeof (elf_i386_pic_plt0_entry));
                      PLT_ENTRY_SIZE - sizeof (elf_i386_pic_plt0_entry));
            }
            }
          else
          else
            {
            {
              memcpy (htab->splt->contents, elf_i386_plt0_entry,
              memcpy (htab->elf.splt->contents, elf_i386_plt0_entry,
                      sizeof(elf_i386_plt0_entry));
                      sizeof(elf_i386_plt0_entry));
              memset (htab->splt->contents + sizeof (elf_i386_plt0_entry),
              memset (htab->elf.splt->contents + sizeof (elf_i386_plt0_entry),
                      htab->plt0_pad_byte,
                      htab->plt0_pad_byte,
                      PLT_ENTRY_SIZE - sizeof (elf_i386_plt0_entry));
                      PLT_ENTRY_SIZE - sizeof (elf_i386_plt0_entry));
              bfd_put_32 (output_bfd,
              bfd_put_32 (output_bfd,
                          (htab->sgotplt->output_section->vma
                          (htab->elf.sgotplt->output_section->vma
                           + htab->sgotplt->output_offset
                           + htab->elf.sgotplt->output_offset
                           + 4),
                           + 4),
                          htab->splt->contents + 2);
                          htab->elf.splt->contents + 2);
              bfd_put_32 (output_bfd,
              bfd_put_32 (output_bfd,
                          (htab->sgotplt->output_section->vma
                          (htab->elf.sgotplt->output_section->vma
                           + htab->sgotplt->output_offset
                           + htab->elf.sgotplt->output_offset
                           + 8),
                           + 8),
                          htab->splt->contents + 8);
                          htab->elf.splt->contents + 8);
 
 
              if (htab->is_vxworks)
              if (htab->is_vxworks)
                {
                {
                  Elf_Internal_Rela rel;
                  Elf_Internal_Rela rel;
 
 
                  /* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 4.
                  /* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 4.
                     On IA32 we use REL relocations so the addend goes in
                     On IA32 we use REL relocations so the addend goes in
                     the PLT directly.  */
                     the PLT directly.  */
                  rel.r_offset = (htab->splt->output_section->vma
                  rel.r_offset = (htab->elf.splt->output_section->vma
                                  + htab->splt->output_offset
                                  + htab->elf.splt->output_offset
                                  + 2);
                                  + 2);
                  rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32);
                  rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32);
                  bfd_elf32_swap_reloc_out (output_bfd, &rel,
                  bfd_elf32_swap_reloc_out (output_bfd, &rel,
                                            htab->srelplt2->contents);
                                            htab->srelplt2->contents);
                  /* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 8.  */
                  /* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 8.  */
                  rel.r_offset = (htab->splt->output_section->vma
                  rel.r_offset = (htab->elf.splt->output_section->vma
                                  + htab->splt->output_offset
                                  + htab->elf.splt->output_offset
                                  + 8);
                                  + 8);
                  rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32);
                  rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32);
                  bfd_elf32_swap_reloc_out (output_bfd, &rel,
                  bfd_elf32_swap_reloc_out (output_bfd, &rel,
                                            htab->srelplt2->contents +
                                            htab->srelplt2->contents +
                                            sizeof (Elf32_External_Rel));
                                            sizeof (Elf32_External_Rel));
                }
                }
            }
            }
 
 
          /* UnixWare sets the entsize of .plt to 4, although that doesn't
          /* UnixWare sets the entsize of .plt to 4, although that doesn't
             really seem like the right value.  */
             really seem like the right value.  */
          elf_section_data (htab->splt->output_section)
          elf_section_data (htab->elf.splt->output_section)
            ->this_hdr.sh_entsize = 4;
            ->this_hdr.sh_entsize = 4;
 
 
          /* Correct the .rel.plt.unloaded relocations.  */
          /* Correct the .rel.plt.unloaded relocations.  */
          if (htab->is_vxworks && !info->shared)
          if (htab->is_vxworks && !info->shared)
            {
            {
              int num_plts = (htab->splt->size / PLT_ENTRY_SIZE) - 1;
              int num_plts = (htab->elf.splt->size / PLT_ENTRY_SIZE) - 1;
              unsigned char *p;
              unsigned char *p;
 
 
              p = htab->srelplt2->contents;
              p = htab->srelplt2->contents;
              if (info->shared)
              if (info->shared)
                p += PLTRESOLVE_RELOCS_SHLIB * sizeof (Elf32_External_Rel);
                p += PLTRESOLVE_RELOCS_SHLIB * sizeof (Elf32_External_Rel);
Line 3939... Line 4521...
                }
                }
            }
            }
        }
        }
    }
    }
 
 
  if (htab->sgotplt)
  if (htab->elf.sgotplt)
    {
    {
      /* Fill in the first three entries in the global offset table.  */
      /* Fill in the first three entries in the global offset table.  */
      if (htab->sgotplt->size > 0)
      if (htab->elf.sgotplt->size > 0)
        {
        {
          bfd_put_32 (output_bfd,
          bfd_put_32 (output_bfd,
                      (sdyn == NULL ? 0
                      (sdyn == NULL ? 0
                       : sdyn->output_section->vma + sdyn->output_offset),
                       : sdyn->output_section->vma + sdyn->output_offset),
                      htab->sgotplt->contents);
                      htab->elf.sgotplt->contents);
          bfd_put_32 (output_bfd, 0, htab->sgotplt->contents + 4);
          bfd_put_32 (output_bfd, 0, htab->elf.sgotplt->contents + 4);
          bfd_put_32 (output_bfd, 0, htab->sgotplt->contents + 8);
          bfd_put_32 (output_bfd, 0, htab->elf.sgotplt->contents + 8);
        }
        }
 
 
      elf_section_data (htab->sgotplt->output_section)->this_hdr.sh_entsize = 4;
      elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize = 4;
    }
    }
 
 
  if (htab->sgot && htab->sgot->size > 0)
  if (htab->elf.sgot && htab->elf.sgot->size > 0)
    elf_section_data (htab->sgot->output_section)->this_hdr.sh_entsize = 4;
    elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
 
 
 
  /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols.  */
 
  htab_traverse (htab->loc_hash_table,
 
                 elf_i386_finish_local_dynamic_symbol,
 
                 info);
 
 
  return TRUE;
  return TRUE;
}
}
 
 
/* Return address for Ith PLT stub in section PLT, for relocation REL
/* Return address for Ith PLT stub in section PLT, for relocation REL
Line 3984... Line 4571...
    return FALSE;
    return FALSE;
 
 
  return _bfd_elf_hash_symbol (h);
  return _bfd_elf_hash_symbol (h);
}
}
 
 
 
/* Hook called by the linker routine which adds symbols from an object
 
   file.  */
 
 
 
static bfd_boolean
 
elf_i386_add_symbol_hook (bfd * abfd ATTRIBUTE_UNUSED,
 
                          struct bfd_link_info * info ATTRIBUTE_UNUSED,
 
                          Elf_Internal_Sym * sym,
 
                          const char ** namep ATTRIBUTE_UNUSED,
 
                          flagword * flagsp ATTRIBUTE_UNUSED,
 
                          asection ** secp ATTRIBUTE_UNUSED,
 
                          bfd_vma * valp ATTRIBUTE_UNUSED)
 
{
 
  if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
 
    elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
 
 
 
  return TRUE;
 
}
 
 
#define TARGET_LITTLE_SYM               bfd_elf32_i386_vec
#define TARGET_LITTLE_SYM               bfd_elf32_i386_vec
#define TARGET_LITTLE_NAME              "elf32-i386"
#define TARGET_LITTLE_NAME              "elf32-i386"
#define ELF_ARCH                        bfd_arch_i386
#define ELF_ARCH                        bfd_arch_i386
#define ELF_MACHINE_CODE                EM_386
#define ELF_MACHINE_CODE                EM_386
#define ELF_MAXPAGESIZE                 0x1000
#define ELF_MAXPAGESIZE                 0x1000
Line 4005... Line 4610...
 
 
#define bfd_elf32_mkobject                    elf_i386_mkobject
#define bfd_elf32_mkobject                    elf_i386_mkobject
 
 
#define bfd_elf32_bfd_is_local_label_name     elf_i386_is_local_label_name
#define bfd_elf32_bfd_is_local_label_name     elf_i386_is_local_label_name
#define bfd_elf32_bfd_link_hash_table_create  elf_i386_link_hash_table_create
#define bfd_elf32_bfd_link_hash_table_create  elf_i386_link_hash_table_create
 
#define bfd_elf32_bfd_link_hash_table_free    elf_i386_link_hash_table_free
#define bfd_elf32_bfd_reloc_type_lookup       elf_i386_reloc_type_lookup
#define bfd_elf32_bfd_reloc_type_lookup       elf_i386_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup       elf_i386_reloc_name_lookup
#define bfd_elf32_bfd_reloc_name_lookup       elf_i386_reloc_name_lookup
 
 
#define elf_backend_adjust_dynamic_symbol     elf_i386_adjust_dynamic_symbol
#define elf_backend_adjust_dynamic_symbol     elf_i386_adjust_dynamic_symbol
#define elf_backend_relocs_compatible         _bfd_elf_relocs_compatible
#define elf_backend_relocs_compatible         _bfd_elf_relocs_compatible
Line 4028... Line 4634...
#define elf_backend_always_size_sections      elf_i386_always_size_sections
#define elf_backend_always_size_sections      elf_i386_always_size_sections
#define elf_backend_omit_section_dynsym \
#define elf_backend_omit_section_dynsym \
  ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
  ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define elf_backend_plt_sym_val               elf_i386_plt_sym_val
#define elf_backend_plt_sym_val               elf_i386_plt_sym_val
#define elf_backend_hash_symbol               elf_i386_hash_symbol
#define elf_backend_hash_symbol               elf_i386_hash_symbol
 
#define elf_backend_add_symbol_hook           elf_i386_add_symbol_hook
 
#undef  elf_backend_post_process_headers
 
#define elf_backend_post_process_headers        _bfd_elf_set_osabi
 
 
#include "elf32-target.h"
#include "elf32-target.h"
 
 
/* FreeBSD support.  */
/* FreeBSD support.  */
 
 
Line 4045... Line 4654...
/* The kernel recognizes executables as valid only if they carry a
/* The kernel recognizes executables as valid only if they carry a
   "FreeBSD" label in the ELF header.  So we put this label on all
   "FreeBSD" label in the ELF header.  So we put this label on all
   executables and (for simplicity) also all other object files.  */
   executables and (for simplicity) also all other object files.  */
 
 
static void
static void
elf_i386_post_process_headers (bfd *abfd,
elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info)
                               struct bfd_link_info *info ATTRIBUTE_UNUSED)
 
{
{
  Elf_Internal_Ehdr *i_ehdrp;
  _bfd_elf_set_osabi (abfd, info);
 
 
  i_ehdrp = elf_elfheader (abfd);
 
 
 
  /* Put an ABI label supported by FreeBSD >= 4.1.  */
 
  i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
 
#ifdef OLD_FREEBSD_ABI_LABEL
#ifdef OLD_FREEBSD_ABI_LABEL
  /* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard.  */
  /* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard.  */
  memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8);
  memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8);
#endif
#endif
}
}
 
 
#undef  elf_backend_post_process_headers
#undef  elf_backend_post_process_headers
#define elf_backend_post_process_headers        elf_i386_post_process_headers
#define elf_backend_post_process_headers        elf_i386_fbsd_post_process_headers
#undef  elf32_bed
#undef  elf32_bed
#define elf32_bed                               elf32_i386_fbsd_bed
#define elf32_bed                               elf32_i386_fbsd_bed
 
 
 
#undef elf_backend_add_symbol_hook
 
 
#include "elf32-target.h"
#include "elf32-target.h"
 
 
/* VxWorks support.  */
/* VxWorks support.  */
 
 
#undef  TARGET_LITTLE_SYM
#undef  TARGET_LITTLE_SYM

powered by: WebSVN 2.1.0

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