Remove U suffix from constants for K&R compilers.
[deliverable/binutils-gdb.git] / bfd / elf32-i386.c
index f8b1844685782a7a4056105d3157206bbf537fa6..90efba8dc9bc824f2e0397f6eb3bb4fedf225d12 100644 (file)
@@ -1,5 +1,5 @@
 /* Intel 80386/80486-specific support for 32-bit ELF
-   Copyright 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+   Copyright 1993, 94-98, 1999 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -29,6 +29,11 @@ static void elf_i386_info_to_howto
   PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
 static void elf_i386_info_to_howto_rel
   PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
+static boolean elf_i386_is_local_label_name PARAMS ((bfd *, const char *));
+static struct bfd_hash_entry *elf_i386_link_hash_newfunc
+  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+static struct bfd_link_hash_table *elf_i386_link_hash_table_create
+  PARAMS ((bfd *));
 static boolean elf_i386_check_relocs
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
           const Elf_Internal_Rela *));
@@ -47,45 +52,7 @@ static boolean elf_i386_finish_dynamic_sections
 
 #define USE_REL        1               /* 386 uses REL relocations instead of RELA */
 
-enum reloc_type
-  {
-    R_386_NONE = 0,
-    R_386_32,
-    R_386_PC32,
-    R_386_GOT32,
-    R_386_PLT32,
-    R_386_COPY,
-    R_386_GLOB_DAT,
-    R_386_JUMP_SLOT,
-    R_386_RELATIVE,
-    R_386_GOTOFF,
-    R_386_GOTPC,
-    FIRST_INVALID_RELOC,
-    LAST_INVALID_RELOC = 19,
-    /* The remaining relocs are a GNU extension.  */
-    R_386_16 = 20,
-    R_386_PC16,
-    R_386_8,
-    R_386_PC8,
-    R_386_max
-  };
-
-#if 0
-static CONST char *CONST reloc_type_names[] =
-{
-  "R_386_NONE",
-  "R_386_32",
-  "R_386_PC32",
-  "R_386_GOT32",
-  "R_386_PLT32",
-  "R_386_COPY",
-  "R_386_GLOB_DAT",
-  "R_386_JUMP_SLOT",
-  "R_386_RELATIVE",
-  "R_386_GOTOFF",
-  "R_386_GOTPC",
-};
-#endif
+#include "elf/i386.h"
 
 static reloc_howto_type elf_howto_table[]=
 {
@@ -100,22 +67,54 @@ static reloc_howto_type elf_howto_table[]=
   HOWTO(R_386_RELATIVE,  0,2,32,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_RELATIVE", true,0xffffffff,0xffffffff,false),
   HOWTO(R_386_GOTOFF,    0,2,32,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_GOTOFF",   true,0xffffffff,0xffffffff,false),
   HOWTO(R_386_GOTPC,     0,2,32,true,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_GOTPC",    true,0xffffffff,0xffffffff,true),
-  { 11 },
-  { 12 },
-  { 13 },
-  { 14 },
-  { 15 },
-  { 16 },
-  { 17 },
-  { 18 },
-  { 19 },
+  EMPTY_HOWTO (11),
+  EMPTY_HOWTO (12),
+  EMPTY_HOWTO (13),
+  EMPTY_HOWTO (14),
+  EMPTY_HOWTO (15),
+  EMPTY_HOWTO (16),
+  EMPTY_HOWTO (17),
+  EMPTY_HOWTO (18),
+  EMPTY_HOWTO (19),
   /* The remaining relocs are a GNU extension.  */
   HOWTO(R_386_16,       0,1,16,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_16",       true,0xffff,0xffff,false),
   HOWTO(R_386_PC16,     0,1,16,true, 0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_PC16",     true,0xffff,0xffff,true),
   HOWTO(R_386_8,        0,0,8,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_8",         true,0xff,0xff,false),
-  HOWTO(R_386_PC8,      0,0,8,true, 0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_PC8",       true,0xff,0xff,true),
+  HOWTO(R_386_PC8,      0,0,8,true, 0,complain_overflow_signed, bfd_elf_generic_reloc,"R_386_PC8",         true,0xff,0xff,true),
 };
 
+/* GNU extension to record C++ vtable hierarchy.  */
+static reloc_howto_type elf32_i386_vtinherit_howto =
+  HOWTO (R_386_GNU_VTINHERIT,  /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        NULL,                  /* special_function */
+        "R_386_GNU_VTINHERIT", /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false);
+
+/* GNU extension to record C++ vtable member usage.  */
+static reloc_howto_type elf32_i386_vtentry_howto =
+  HOWTO (R_386_GNU_VTENTRY,    /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        0,                     /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        _bfd_elf_rel_vtable_reloc_fn, /* special_function */
+        "R_386_GNU_VTENTRY",   /* name */
+        false,                 /* partial_inplace */
+        0,                     /* src_mask */
+        0,                     /* dst_mask */
+        false);
+
 #ifdef DEBUG_GEN_RELOC
 #define TRACE(str) fprintf (stderr, "i386 bfd reloc lookup %d (%s)\n", code, str)
 #else
@@ -124,7 +123,7 @@ static reloc_howto_type elf_howto_table[]=
 
 static reloc_howto_type *
 elf_i386_reloc_type_lookup (abfd, code)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      bfd_reloc_code_real_type code;
 {
   switch (code)
@@ -137,6 +136,10 @@ elf_i386_reloc_type_lookup (abfd, code)
       TRACE ("BFD_RELOC_32");
       return &elf_howto_table[ (int)R_386_32 ];
 
+    case BFD_RELOC_CTOR:
+      TRACE ("BFD_RELOC_CTOR");
+      return &elf_howto_table[ (int)R_386_32 ];
+
     case BFD_RELOC_32_PCREL:
       TRACE ("BFD_RELOC_PC32");
       return &elf_howto_table[ (int)R_386_PC32 ];
@@ -190,6 +193,14 @@ elf_i386_reloc_type_lookup (abfd, code)
       TRACE ("BFD_RELOC_8_PCREL");
       return &elf_howto_table[(int) R_386_PC8];
 
+    case BFD_RELOC_VTABLE_INHERIT:
+      TRACE ("BFD_RELOC_VTABLE_INHERIT");
+      return &elf32_i386_vtinherit_howto;
+
+    case BFD_RELOC_VTABLE_ENTRY:
+      TRACE ("BFD_RELOC_VTABLE_ENTRY");
+      return &elf32_i386_vtentry_howto;
+
     default:
       break;
     }
@@ -200,26 +211,52 @@ elf_i386_reloc_type_lookup (abfd, code)
 
 static void
 elf_i386_info_to_howto (abfd, cache_ptr, dst)
-     bfd               *abfd;
-     arelent           *cache_ptr;
-     Elf32_Internal_Rela *dst;
+     bfd               *abfd ATTRIBUTE_UNUSED;
+     arelent           *cache_ptr ATTRIBUTE_UNUSED;
+     Elf32_Internal_Rela *dst ATTRIBUTE_UNUSED;
 {
   abort ();
 }
 
 static void
 elf_i386_info_to_howto_rel (abfd, cache_ptr, dst)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      arelent *cache_ptr;
      Elf32_Internal_Rel *dst;
 {
-  enum reloc_type type;
+  enum elf_i386_reloc_type type;
+
+  type = (enum elf_i386_reloc_type) ELF32_R_TYPE (dst->r_info);
+  if (type == R_386_GNU_VTINHERIT)
+    cache_ptr->howto = &elf32_i386_vtinherit_howto;
+  else if (type == R_386_GNU_VTENTRY)
+    cache_ptr->howto = &elf32_i386_vtentry_howto;
+  else if (type < R_386_max
+          && (type < FIRST_INVALID_RELOC || type > LAST_INVALID_RELOC))
+    cache_ptr->howto = &elf_howto_table[(int) type];
+  else
+    {
+      (*_bfd_error_handler) (_("%s: invalid relocation type %d"),
+                            bfd_get_filename (abfd), (int) type);
+      cache_ptr->howto = &elf_howto_table[(int) R_386_NONE];
+    }
+}
+
+/* Return whether a symbol name implies a local label.  The UnixWare
+   2.1 cc generates temporary symbols that start with .X, so we
+   recognize them here.  FIXME: do other SVR4 compilers also use .X?.
+   If so, we should move the .X recognition into
+   _bfd_elf_is_local_label_name.  */
 
-  type = (enum reloc_type) ELF32_R_TYPE (dst->r_info);
-  BFD_ASSERT (type < R_386_max);
-  BFD_ASSERT (type < FIRST_INVALID_RELOC || type > LAST_INVALID_RELOC);
+static boolean
+elf_i386_is_local_label_name (abfd, name)
+     bfd *abfd;
+     const char *name;
+{
+  if (name[0] == '.' && name[1] == 'X')
+    return true;
 
-  cache_ptr->howto = &elf_howto_table[(int) type];
+  return _bfd_elf_is_local_label_name (abfd, name);
 }
 \f
 /* Functions for the i386 ELF linker.  */
@@ -279,6 +316,115 @@ static const bfd_byte elf_i386_pic_plt_entry[PLT_ENTRY_SIZE] =
   0, 0, 0, 0   /* replaced with offset to start of .plt.  */
 };
 
+/* The i386 linker needs to keep track of the number of relocs that it
+   decides to copy in check_relocs for each symbol.  This is so that
+   it can discard PC relative relocs if it doesn't need them when
+   linking with -Bsymbolic.  We store the information in a field
+   extending the regular ELF linker hash table.  */
+
+/* This structure keeps track of the number of PC relative relocs we
+   have copied for a given symbol.  */
+
+struct elf_i386_pcrel_relocs_copied
+{
+  /* Next section.  */
+  struct elf_i386_pcrel_relocs_copied *next;
+  /* A section in dynobj.  */
+  asection *section;
+  /* Number of relocs copied in this section.  */
+  bfd_size_type count;
+};
+
+/* i386 ELF linker hash entry.  */
+
+struct elf_i386_link_hash_entry
+{
+  struct elf_link_hash_entry root;
+
+  /* Number of PC relative relocs copied for this symbol.  */
+  struct elf_i386_pcrel_relocs_copied *pcrel_relocs_copied;
+};
+
+/* i386 ELF linker hash table.  */
+
+struct elf_i386_link_hash_table
+{
+  struct elf_link_hash_table root;
+};
+
+/* Declare this now that the above structures are defined.  */
+
+static boolean elf_i386_discard_copies
+  PARAMS ((struct elf_i386_link_hash_entry *, PTR));
+
+/* Traverse an i386 ELF linker hash table.  */
+
+#define elf_i386_link_hash_traverse(table, func, info)                 \
+  (elf_link_hash_traverse                                              \
+   (&(table)->root,                                                    \
+    (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \
+    (info)))
+
+/* Get the i386 ELF linker hash table from a link_info structure.  */
+
+#define elf_i386_hash_table(p) \
+  ((struct elf_i386_link_hash_table *) ((p)->hash))
+
+/* Create an entry in an i386 ELF linker hash table.  */
+
+static struct bfd_hash_entry *
+elf_i386_link_hash_newfunc (entry, table, string)
+     struct bfd_hash_entry *entry;
+     struct bfd_hash_table *table;
+     const char *string;
+{
+  struct elf_i386_link_hash_entry *ret =
+    (struct elf_i386_link_hash_entry *) entry;
+
+  /* Allocate the structure if it has not already been allocated by a
+     subclass.  */
+  if (ret == (struct elf_i386_link_hash_entry *) NULL)
+    ret = ((struct elf_i386_link_hash_entry *)
+          bfd_hash_allocate (table,
+                             sizeof (struct elf_i386_link_hash_entry)));
+  if (ret == (struct elf_i386_link_hash_entry *) NULL)
+    return (struct bfd_hash_entry *) ret;
+
+  /* Call the allocation method of the superclass.  */
+  ret = ((struct elf_i386_link_hash_entry *)
+        _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
+                                    table, string));
+  if (ret != (struct elf_i386_link_hash_entry *) NULL)
+    {
+      ret->pcrel_relocs_copied = NULL;
+    }
+
+  return (struct bfd_hash_entry *) ret;
+}
+
+/* Create an i386 ELF linker hash table.  */
+
+static struct bfd_link_hash_table *
+elf_i386_link_hash_table_create (abfd)
+     bfd *abfd;
+{
+  struct elf_i386_link_hash_table *ret;
+
+  ret = ((struct elf_i386_link_hash_table *)
+        bfd_alloc (abfd, sizeof (struct elf_i386_link_hash_table)));
+  if (ret == (struct elf_i386_link_hash_table *) NULL)
+    return NULL;
+
+  if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
+                                      elf_i386_link_hash_newfunc))
+    {
+      bfd_release (abfd, ret);
+      return NULL;
+    }
+
+  return &ret->root.root;
+}
+
 /* Look through the relocs for a section during the first phase, and
    allocate space in the global offset table or procedure linkage
    table.  */
@@ -376,12 +522,12 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
 
          if (h != NULL)
            {
-             if (h->got_offset != (bfd_vma) -1)
+             if (h->got.offset != (bfd_vma) -1)
                {
                  /* We have already allocated space in the .got.  */
                  break;
                }
-             h->got_offset = sgot->_raw_size;
+             h->got.offset = sgot->_raw_size;
 
              /* Make sure this symbol is output as a dynamic symbol.  */
              if (h->dynindx == -1)
@@ -448,8 +594,28 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
 
        case R_386_32:
        case R_386_PC32:
+         if (h != NULL)
+           h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
+
+         /* If we are creating a shared library, and this is a reloc
+             against a global symbol, or a non PC relative reloc
+             against a local symbol, then we need to copy the reloc
+             into the shared library.  However, if we are linking with
+             -Bsymbolic, we do not need to copy a reloc against a
+             global symbol which is defined in an object we are
+             including in the link (i.e., DEF_REGULAR is set).  At
+             this point we have not seen all the input files, so it is
+             possible that DEF_REGULAR is not set now but will be set
+             later (it is never cleared).  We account for that
+             possibility below by storing information in the
+             pcrel_relocs_copied field of the hash table entry.  */
          if (info->shared
-             && (ELF32_R_TYPE (rel->r_info) != R_386_PC32 || h != NULL))
+             && (sec->flags & SEC_ALLOC) != 0
+             && (ELF32_R_TYPE (rel->r_info) != R_386_PC32
+                 || (h != NULL
+                     && (! info->symbolic
+                         || (h->elf_link_hash_flags
+                             & ELF_LINK_HASH_DEF_REGULAR) == 0))))
            {
              /* When creating a shared object, we must copy these
                  reloc types into the output file.  We create a reloc
@@ -487,10 +653,59 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
                }
 
              sreloc->_raw_size += sizeof (Elf32_External_Rel);
+
+             /* If we are linking with -Bsymbolic, and this is a
+                 global symbol, we count the number of PC relative
+                 relocations we have entered for this symbol, so that
+                 we can discard them again if the symbol is later
+                 defined by a regular object.  Note that this function
+                 is only called if we are using an elf_i386 linker
+                 hash table, which means that h is really a pointer to
+                 an elf_i386_link_hash_entry.  */
+             if (h != NULL && info->symbolic
+                 && ELF32_R_TYPE (rel->r_info) == R_386_PC32)
+               {
+                 struct elf_i386_link_hash_entry *eh;
+                 struct elf_i386_pcrel_relocs_copied *p;
+
+                 eh = (struct elf_i386_link_hash_entry *) h;
+
+                 for (p = eh->pcrel_relocs_copied; p != NULL; p = p->next)
+                   if (p->section == sreloc)
+                     break;
+
+                 if (p == NULL)
+                   {
+                     p = ((struct elf_i386_pcrel_relocs_copied *)
+                          bfd_alloc (dynobj, sizeof *p));
+                     if (p == NULL)
+                       return false;
+                     p->next = eh->pcrel_relocs_copied;
+                     eh->pcrel_relocs_copied = p;
+                     p->section = sreloc;
+                     p->count = 0;
+                   }
+
+                 ++p->count;
+               }
            }
 
          break;
 
+         /* This relocation describes the C++ object vtable hierarchy.
+            Reconstruct it for later use during GC.  */
+       case R_386_GNU_VTINHERIT:
+         if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
+           return false;
+         break;
+
+         /* This relocation describes which C++ vtable entries are actually
+            used.  Record for later use during GC.  */
+       case R_386_GNU_VTENTRY:
+         if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
+           return false;
+         break;
+
        default:
          break;
        }
@@ -499,6 +714,70 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
   return true;
 }
 
+/* Return the section that should be marked against GC for a given
+   relocation.  */
+
+static asection *
+elf_i386_gc_mark_hook (abfd, info, rel, h, sym)
+     bfd *abfd;
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+     Elf_Internal_Rela *rel;
+     struct elf_link_hash_entry *h;
+     Elf_Internal_Sym *sym;
+{
+  if (h != NULL)
+    {
+      switch (ELF32_R_TYPE (rel->r_info))
+       {
+       case R_386_GNU_VTINHERIT:
+       case R_386_GNU_VTENTRY:
+         break;
+
+       default:
+         switch (h->root.type)
+           {
+           case bfd_link_hash_defined:
+           case bfd_link_hash_defweak:
+             return h->root.u.def.section;
+
+           case bfd_link_hash_common:
+             return h->root.u.c.p->section;
+
+           default:
+             break;
+           }
+       }
+    }
+  else
+    {
+      if (!(elf_bad_symtab (abfd)
+           && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
+         && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
+               && sym->st_shndx != SHN_COMMON))
+       {
+         return bfd_section_from_elf_index (abfd, sym->st_shndx);
+       }
+    }
+
+  return NULL;
+}
+
+/* Update the got entry reference counts for the section being removed.  */
+
+static boolean
+elf_i386_gc_sweep_hook (abfd, info, sec, relocs)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     struct bfd_link_info *info ATTRIBUTE_UNUSED;
+     asection *sec ATTRIBUTE_UNUSED;
+     const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
+{
+  /* ??? It would seem that the existing i386 code does no sort
+     of reference counting or whatnot on its GOT and PLT entries,
+     so it is not possible to garbage collect them at this time.  */
+
+  return true;
+}
+
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  The current definition is in some section of the
    dynamic object, but we're not including those sections.  We have to
@@ -573,7 +852,7 @@ elf_i386_adjust_dynamic_symbol (info, h)
          h->root.u.def.value = s->_raw_size;
        }
 
-      h->plt_offset = s->_raw_size;
+      h->plt.offset = s->_raw_size;
 
       /* Make room for this entry.  */
       s->_raw_size += PLT_ENTRY_SIZE;
@@ -616,6 +895,11 @@ elf_i386_adjust_dynamic_symbol (info, h)
   if (info->shared)
     return true;
 
+  /* If there are no references to this symbol that do not use the
+     GOT, we don't need to generate a copy reloc.  */
+  if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) == 0)
+    return true;
+
   /* We must allocate the symbol in our .dynbss section, which will
      become part of the .bss section of the executable.  There will be
      an entry for this symbol in the .dynsym section.  The dynamic
@@ -629,14 +913,11 @@ elf_i386_adjust_dynamic_symbol (info, h)
   s = bfd_get_section_by_name (dynobj, ".dynbss");
   BFD_ASSERT (s != NULL);
 
-  /* If the symbol is currently defined in the .bss section of the
-     dynamic object, then it is OK to simply initialize it to zero.
-     If the symbol is in some other section, we must generate a
-     R_386_COPY reloc to tell the dynamic linker to copy the initial
-     value out of the dynamic object and into the runtime process
-     image.  We need to remember the offset into the .rel.bss section
-     we are going to use.  */
-  if ((h->root.u.def.section->flags & SEC_LOAD) != 0)
+  /* We must generate a R_386_COPY reloc to tell the dynamic linker to
+     copy the initial value out of the dynamic object and into the
+     runtime process image.  We need to remember the offset into the
+     .rel.bss section we are going to use.  */
+  if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
     {
       asection *srel;
 
@@ -710,6 +991,15 @@ elf_i386_size_dynamic_sections (output_bfd, info)
        s->_raw_size = 0;
     }
 
+  /* If this is a -Bsymbolic shared link, then we need to discard all
+     PC relative relocs against symbols defined in a regular object.
+     We allocated space for them in the check_relocs routine, but we
+     will not fill them in in the relocate_section routine.  */
+  if (info->shared && info->symbolic)
+    elf_i386_link_hash_traverse (elf_i386_hash_table (info),
+                                elf_i386_discard_copies,
+                                (PTR) NULL);
+
   /* The check_relocs and adjust_dynamic_symbol entry points have
      determined the sizes of the various dynamic sections.  Allocate
      memory for them.  */
@@ -767,6 +1057,8 @@ elf_i386_size_dynamic_sections (output_bfd, info)
                  than .rel.plt.  */
              if (strcmp (name, ".rel.plt") != 0)
                {
+                 const char *outname;
+
                  relocs = true;
 
                  /* If this relocation section applies to a read only
@@ -774,9 +1066,12 @@ elf_i386_size_dynamic_sections (output_bfd, info)
                     entry.  The entries in the .rel.plt section
                     really apply to the .got section, which we
                     created ourselves and so know is not readonly.  */
-                 target = bfd_get_section_by_name (output_bfd, name + 4);
+                 outname = bfd_get_section_name (output_bfd,
+                                                 s->output_section);
+                 target = bfd_get_section_by_name (output_bfd, outname + 4);
                  if (target != NULL
-                     && (target->flags & SEC_READONLY) != 0)
+                     && (target->flags & SEC_READONLY) != 0
+                     && (target->flags & SEC_ALLOC) != 0)
                    reltext = true;
                }
 
@@ -793,15 +1088,7 @@ elf_i386_size_dynamic_sections (output_bfd, info)
 
       if (strip)
        {
-         asection **spp;
-
-         for (spp = &s->output_section->owner->sections;
-              *spp != s->output_section;
-              spp = &(*spp)->next)
-           ;
-         *spp = s->output_section->next;
-         --s->output_section->owner->section_count;
-
+         _bfd_strip_section_from_output (info, s);
          continue;
        }
 
@@ -852,6 +1139,31 @@ elf_i386_size_dynamic_sections (output_bfd, info)
   return true;
 }
 
+/* This function is called via elf_i386_link_hash_traverse if we are
+   creating a shared object with -Bsymbolic.  It discards the space
+   allocated to copy PC relative relocs against symbols which are
+   defined in regular objects.  We allocated space for them in the
+   check_relocs routine, but we won't fill them in in the
+   relocate_section routine.  */
+
+/*ARGSUSED*/
+static boolean
+elf_i386_discard_copies (h, ignore)
+     struct elf_i386_link_hash_entry *h;
+     PTR ignore ATTRIBUTE_UNUSED;
+{
+  struct elf_i386_pcrel_relocs_copied *s;
+
+  /* We only discard relocs for symbols defined in a regular object.  */
+  if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+    return true;
+
+  for (s = h->pcrel_relocs_copied; s != NULL; s = s->next)
+    s->section->_raw_size -= s->count * sizeof (Elf32_External_Rel);
+
+  return true;
+}
+
 /* Relocate an i386 ELF section.  */
 
 static boolean
@@ -899,6 +1211,9 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
       bfd_reloc_status_type r;
 
       r_type = ELF32_R_TYPE (rel->r_info);
+      if (r_type == R_386_GNU_VTINHERIT
+         || r_type == R_386_GNU_VTENTRY)
+       continue;
       if (r_type < 0
          || r_type >= (int) R_386_max
          || (r_type >= (int) FIRST_INVALID_RELOC
@@ -958,19 +1273,25 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
              sec = h->root.u.def.section;
              if (r_type == R_386_GOTPC
                  || (r_type == R_386_PLT32
-                     && h->plt_offset != (bfd_vma) -1)
+                     && h->plt.offset != (bfd_vma) -1)
                  || (r_type == R_386_GOT32
                      && elf_hash_table (info)->dynamic_sections_created
                      && (! info->shared
-                         || ! info->symbolic
+                         || (! info->symbolic && h->dynindx != -1)
                          || (h->elf_link_hash_flags
                              & ELF_LINK_HASH_DEF_REGULAR) == 0))
                  || (info->shared
-                     && (! info->symbolic
+                     && ((! info->symbolic && h->dynindx != -1)
                          || (h->elf_link_hash_flags
                              & ELF_LINK_HASH_DEF_REGULAR) == 0)
                      && (r_type == R_386_32
-                         || r_type == R_386_PC32)))
+                         || r_type == R_386_PC32)
+                     && ((input_section->flags & SEC_ALLOC) != 0
+                         /* DWARF will emit R_386_32 relocations in its
+                            sections against symbols defined externally
+                            in shared libraries.  We can't do anything
+                            with them here.  */
+                         || (input_section->flags & SEC_DEBUGGING) != 0)))
                {
                  /* In these cases, we don't need the relocation
                      value.  We check specially because in some
@@ -980,7 +1301,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
              else if (sec->output_section == NULL)
                {
                  (*_bfd_error_handler)
-                   ("%s: warning: unresolvable relocation against symbol `%s' from %s section",
+                   (_("%s: warning: unresolvable relocation against symbol `%s' from %s section"),
                     bfd_get_filename (input_bfd), h->root.root.string,
                     bfd_get_section_name (input_bfd, input_section));
                  relocation = 0;
@@ -992,13 +1313,14 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
            }
          else if (h->root.type == bfd_link_hash_undefweak)
            relocation = 0;
-         else if (info->shared && !info->symbolic)
+         else if (info->shared && !info->symbolic && !info->no_undefined)
            relocation = 0;
          else
            {
              if (! ((*info->callbacks->undefined_symbol)
                     (info, h->root.root.string, input_bfd,
-                     input_section, rel->r_offset)))
+                     input_section, rel->r_offset,
+                     (!info->shared || info->no_undefined))))
                return false;
              relocation = 0;
            }
@@ -1019,20 +1341,21 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
            {
              bfd_vma off;
 
-             off = h->got_offset;
+             off = h->got.offset;
              BFD_ASSERT (off != (bfd_vma) -1);
 
              if (! elf_hash_table (info)->dynamic_sections_created
                  || (info->shared
-                     && info->symbolic
+                     && (info->symbolic || h->dynindx == -1)
                      && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
                {
                  /* This is actually a static link, or it is a
                     -Bsymbolic link and the symbol is defined
-                    locally.  We must initialize this entry in the
-                    global offset table.  Since the offset must
-                    always be a multiple of 4, we use the least
-                    significant bit to record whether we have
+                    locally, or the symbol was forced to be local
+                    because of a version file.  We must initialize
+                    this entry in the global offset table.  Since the
+                    offset must always be a multiple of 4, we use the
+                    least significant bit to record whether we have
                     initialized it already.
 
                     When doing a dynamic link, we create a .rel.got
@@ -1044,7 +1367,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
                    {
                      bfd_put_32 (output_bfd, relocation,
                                  sgot->contents + off);
-                     h->got_offset |= 1;
+                     h->got.offset |= 1;
                    }
                }
 
@@ -1136,7 +1459,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
          if (h == NULL)
            break;
 
-         if (h->plt_offset == (bfd_vma) -1)
+         if (h->plt.offset == (bfd_vma) -1)
            {
              /* We didn't make a PLT entry for this symbol.  This
                  happens when statically linking PIC code, or when
@@ -1152,21 +1475,23 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
 
          relocation = (splt->output_section->vma
                        + splt->output_offset
-                       + h->plt_offset);
+                       + h->plt.offset);
 
          break;
 
        case R_386_32:
        case R_386_PC32:
          if (info->shared
+             && (input_section->flags & SEC_ALLOC) != 0
              && (r_type != R_386_PC32
                  || (h != NULL
+                     && h->dynindx != -1
                      && (! info->symbolic
                          || (h->elf_link_hash_flags
                              & ELF_LINK_HASH_DEF_REGULAR) == 0))))
            {
              Elf_Internal_Rel outrel;
-             boolean relocate;
+             boolean skip, relocate;
 
              /* When generating a shared object, these relocations
                 are copied into the output file to be resolved at run
@@ -1192,10 +1517,33 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
                  BFD_ASSERT (sreloc != NULL);
                }
 
-             outrel.r_offset = (rel->r_offset
-                                + input_section->output_section->vma
-                                + input_section->output_offset);
-             if (r_type == R_386_PC32)
+             skip = false;
+
+             if (elf_section_data (input_section)->stab_info == NULL)
+               outrel.r_offset = rel->r_offset;
+             else
+               {
+                 bfd_vma off;
+
+                 off = (_bfd_stab_section_offset
+                        (output_bfd, &elf_hash_table (info)->stab_info,
+                         input_section,
+                         &elf_section_data (input_section)->stab_info,
+                         rel->r_offset));
+                 if (off == (bfd_vma) -1)
+                   skip = true;
+                 outrel.r_offset = off;
+               }
+
+             outrel.r_offset += (input_section->output_section->vma
+                                 + input_section->output_offset);
+
+             if (skip)
+               {
+                 memset (&outrel, 0, sizeof outrel);
+                 relocate = false;
+               }
+             else if (r_type == R_386_PC32)
                {
                  BFD_ASSERT (h != NULL && h->dynindx != -1);
                  relocate = false;
@@ -1203,8 +1551,10 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
                }
              else
                {
+                 /* h->dynindx may be -1 if this symbol was marked to
+                     become local.  */
                  if (h == NULL
-                     || (info->symbolic
+                     || ((info->symbolic || h->dynindx == -1)
                          && (h->elf_link_hash_flags
                              & ELF_LINK_HASH_DEF_REGULAR) != 0))
                    {
@@ -1293,7 +1643,7 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym)
 
   dynobj = elf_hash_table (info)->dynobj;
 
-  if (h->plt_offset != (bfd_vma) -1)
+  if (h->plt.offset != (bfd_vma) -1)
     {
       asection *splt;
       asection *sgot;
@@ -1316,7 +1666,7 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym)
         corresponds to this symbol.  This is the index of this symbol
         in all the symbols for which we are making plt entries.  The
         first entry in the procedure linkage table is reserved.  */
-      plt_index = h->plt_offset / PLT_ENTRY_SIZE - 1;
+      plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;
 
       /* Get the offset into the .got table of the entry that
         corresponds to this function.  Each .got entry is 4 bytes.
@@ -1326,32 +1676,32 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym)
       /* Fill in the entry in the procedure linkage table.  */
       if (! info->shared)
        {
-         memcpy (splt->contents + h->plt_offset, elf_i386_plt_entry,
+         memcpy (splt->contents + h->plt.offset, elf_i386_plt_entry,
                  PLT_ENTRY_SIZE);
          bfd_put_32 (output_bfd,
                      (sgot->output_section->vma
                       + sgot->output_offset
                       + got_offset),
-                     splt->contents + h->plt_offset + 2);
+                     splt->contents + h->plt.offset + 2);
        }
       else
        {
-         memcpy (splt->contents + h->plt_offset, elf_i386_pic_plt_entry,
+         memcpy (splt->contents + h->plt.offset, elf_i386_pic_plt_entry,
                  PLT_ENTRY_SIZE);
          bfd_put_32 (output_bfd, got_offset,
-                     splt->contents + h->plt_offset + 2);
+                     splt->contents + h->plt.offset + 2);
        }
 
       bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rel),
-                 splt->contents + h->plt_offset + 7);
-      bfd_put_32 (output_bfd, - (h->plt_offset + PLT_ENTRY_SIZE),
-                 splt->contents + h->plt_offset + 12);
+                 splt->contents + h->plt.offset + 7);
+      bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE),
+                 splt->contents + h->plt.offset + 12);
 
       /* Fill in the entry in the global offset table.  */
       bfd_put_32 (output_bfd,
                  (splt->output_section->vma
                   + splt->output_offset
-                  + h->plt_offset
+                  + h->plt.offset
                   + 6),
                  sgot->contents + got_offset);
 
@@ -1372,7 +1722,7 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym)
        }
     }
 
-  if (h->got_offset != (bfd_vma) -1)
+  if (h->got.offset != (bfd_vma) -1)
     {
       asection *sgot;
       asection *srel;
@@ -1381,27 +1731,26 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym)
       /* This symbol has an entry in the global offset table.  Set it
         up.  */
 
-      BFD_ASSERT (h->dynindx != -1);
-
       sgot = bfd_get_section_by_name (dynobj, ".got");
       srel = bfd_get_section_by_name (dynobj, ".rel.got");
       BFD_ASSERT (sgot != NULL && srel != NULL);
 
       rel.r_offset = (sgot->output_section->vma
                      + sgot->output_offset
-                     + (h->got_offset &~ 1));
+                     + (h->got.offset &~ 1));
 
       /* If this is a -Bsymbolic link, and the symbol is defined
-        locally, we just want to emit a RELATIVE reloc.  The entry in
-        the global offset table will already have been initialized in
-        the relocate_section function.  */
+        locally, we just want to emit a RELATIVE reloc.  Likewise if
+        the symbol was forced to be local because of a version file.
+        The entry in the global offset table will already have been
+        initialized in the relocate_section function.  */
       if (info->shared
-         && info->symbolic
+         && (info->symbolic || h->dynindx == -1)
          && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
        rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
       else
        {
-         bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got_offset);
+         bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset);
          rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT);
        }
 
@@ -1466,8 +1815,7 @@ elf_i386_finish_dynamic_sections (output_bfd, info)
       asection *splt;
       Elf32_External_Dyn *dyncon, *dynconend;
 
-      splt = bfd_get_section_by_name (dynobj, ".plt");
-      BFD_ASSERT (splt != NULL && sdyn != NULL);
+      BFD_ASSERT (sdyn != NULL);
 
       dyncon = (Elf32_External_Dyn *) sdyn->contents;
       dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
@@ -1530,7 +1878,8 @@ elf_i386_finish_dynamic_sections (output_bfd, info)
        }
 
       /* Fill in the first entry in the procedure linkage table.  */
-      if (splt->_raw_size > 0)
+      splt = bfd_get_section_by_name (dynobj, ".plt");
+      if (splt && splt->_raw_size > 0)
        {
          if (info->shared)
            memcpy (splt->contents, elf_i386_pic_plt0_entry, PLT_ENTRY_SIZE);
@@ -1544,11 +1893,11 @@ elf_i386_finish_dynamic_sections (output_bfd, info)
                          sgot->output_section->vma + sgot->output_offset + 8,
                          splt->contents + 8);
            }
-       }
 
-      /* UnixWare sets the entsize of .plt to 4, although that doesn't
-        really seem like the right value.  */
-      elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
+         /* UnixWare sets the entsize of .plt to 4, although that doesn't
+            really seem like the right value.  */
+         elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
+       }
     }
 
   /* Fill in the first three entries in the global offset table.  */
@@ -1573,12 +1922,16 @@ elf_i386_finish_dynamic_sections (output_bfd, info)
 #define TARGET_LITTLE_NAME             "elf32-i386"
 #define ELF_ARCH                       bfd_arch_i386
 #define ELF_MACHINE_CODE               EM_386
+#define ELF_MAXPAGESIZE                        0x1000
 #define elf_info_to_howto              elf_i386_info_to_howto
 #define elf_info_to_howto_rel          elf_i386_info_to_howto_rel
 #define bfd_elf32_bfd_reloc_type_lookup        elf_i386_reloc_type_lookup
-#define ELF_MAXPAGESIZE                        0x1000
+#define bfd_elf32_bfd_is_local_label_name \
+                                       elf_i386_is_local_label_name
 #define elf_backend_create_dynamic_sections \
                                        _bfd_elf_create_dynamic_sections
+#define bfd_elf32_bfd_link_hash_table_create \
+                                       elf_i386_link_hash_table_create
 #define elf_backend_check_relocs       elf_i386_check_relocs
 #define elf_backend_adjust_dynamic_symbol \
                                        elf_i386_adjust_dynamic_symbol
@@ -1589,8 +1942,14 @@ elf_i386_finish_dynamic_sections (output_bfd, info)
                                        elf_i386_finish_dynamic_symbol
 #define elf_backend_finish_dynamic_sections \
                                        elf_i386_finish_dynamic_sections
-#define elf_backend_want_got_plt 1
-#define elf_backend_plt_readonly 1
-#define elf_backend_want_plt_sym 0
+#define elf_backend_gc_mark_hook       elf_i386_gc_mark_hook
+#define elf_backend_gc_sweep_hook      elf_i386_gc_sweep_hook
+
+#define elf_backend_can_gc_sections    1
+#define elf_backend_want_got_plt       1
+#define elf_backend_plt_readonly       1
+#define elf_backend_want_plt_sym       0
+#define elf_backend_got_header_size    12
+#define elf_backend_plt_header_size    PLT_ENTRY_SIZE
 
 #include "elf32-target.h"
This page took 0.036265 seconds and 4 git commands to generate.