* elf-bfd.h (struct elf_link_local_dynamic_entry): New.
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 123bccd71480dfe40134340071499a5b7a92c584..93155b11af79a45b47e5254697eb4e821183103c 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF linking support for BFD.
-   Copyright 1993, 1995 Free Software Foundation, Inc.
+   Copyright 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -15,14 +15,14 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
 #include "bfdlink.h"
 #include "libbfd.h"
 #define ARCH_SIZE 0
-#include "libelf.h"
+#include "elf-bfd.h"
 
 boolean
 _bfd_elf_create_got_section (abfd, info)
@@ -33,17 +33,26 @@ _bfd_elf_create_got_section (abfd, info)
   register asection *s;
   struct elf_link_hash_entry *h;
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  int ptralign;
 
   /* This function may be called more than once.  */
   if (bfd_get_section_by_name (abfd, ".got") != NULL)
     return true;
 
-  flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+  switch (bed->s->arch_size)
+    {
+    case 32: ptralign = 2; break;
+    case 64: ptralign = 3; break;
+    default: abort();
+    }
+
+  flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+          | SEC_LINKER_CREATED);
 
   s = bfd_make_section (abfd, ".got");
   if (s == NULL
       || !bfd_set_section_flags (abfd, s, flags)
-      || !bfd_set_section_alignment (abfd, s, 2))
+      || !bfd_set_section_alignment (abfd, s, ptralign))
     return false;
 
   if (bed->want_got_plt)
@@ -51,7 +60,7 @@ _bfd_elf_create_got_section (abfd, info)
       s = bfd_make_section (abfd, ".got.plt");
       if (s == NULL
          || !bfd_set_section_flags (abfd, s, flags)
-         || !bfd_set_section_alignment (abfd, s, 2))
+         || !bfd_set_section_alignment (abfd, s, ptralign))
        return false;
     }
 
@@ -61,9 +70,9 @@ _bfd_elf_create_got_section (abfd, info)
      a global offset table.  */
   h = NULL;
   if (!(_bfd_generic_link_add_one_symbol
-       (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s, (bfd_vma) 0,
-        (const char *) NULL, false, get_elf_backend_data (abfd)->collect,
-        (struct bfd_link_hash_entry **) &h)))
+       (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s,
+        bed->got_symbol_offset, (const char *) NULL, false,
+        bed->collect, (struct bfd_link_hash_entry **) &h)))
     return false;
   h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
   h->type = STT_OBJECT;
@@ -72,11 +81,14 @@ _bfd_elf_create_got_section (abfd, info)
       && ! _bfd_elf_link_record_dynamic_symbol (info, h))
     return false;
 
-  /* The first three global offset table entries are reserved.  */
-  s->_raw_size += 3 * 4;
+  elf_hash_table (info)->hgot = h;
+
+  /* The first bit of the global offset table is the header.  */
+  s->_raw_size += bed->got_header_size + bed->got_symbol_offset;
 
   return true;
 }
+\f
 
 /* Create dynamic sections when linking against a dynamic object.  */
 
@@ -85,21 +97,35 @@ _bfd_elf_create_dynamic_sections (abfd, info)
      bfd *abfd;
      struct bfd_link_info *info;
 {
-  flagword flags;
+  flagword flags, pltflags;
   register asection *s;
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  int ptralign = 0;
+
+  switch (bed->s->arch_size)
+    {
+    case 32: ptralign = 2; break;
+    case 64: ptralign = 3; break;
+    default: abort();
+    }
 
   /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
      .rel[a].bss sections.  */
 
-  flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+  flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+          | SEC_LINKER_CREATED);
+
+  pltflags = flags;
+  pltflags |= SEC_CODE;
+  if (bed->plt_not_loaded)
+    pltflags &= ~ (SEC_LOAD | SEC_HAS_CONTENTS);
+  if (bed->plt_readonly)
+    pltflags |= SEC_READONLY;
 
   s = bfd_make_section (abfd, ".plt");
   if (s == NULL
-      || ! bfd_set_section_flags (abfd, s,
-                                 (flags | SEC_CODE
-                                  | (bed->plt_readonly ? SEC_READONLY : 0)))
-      || ! bfd_set_section_alignment (abfd, s, 2))
+      || ! bfd_set_section_flags (abfd, s, pltflags)
+      || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
     return false;
 
   if (bed->want_plt_sym)
@@ -121,10 +147,11 @@ _bfd_elf_create_dynamic_sections (abfd, info)
        return false;
     }
 
-  s = bfd_make_section (abfd, bed->use_rela_p ? ".rela.plt" : ".rel.plt");
+  s = bfd_make_section (abfd, 
+                       bed->default_use_rela_p ? ".rela.plt" : ".rel.plt");
   if (s == NULL
       || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
-      || ! bfd_set_section_alignment (abfd, s, 2))
+      || ! bfd_set_section_alignment (abfd, s, ptralign))
     return false;
 
   if (! _bfd_elf_create_got_section (abfd, info))
@@ -154,15 +181,18 @@ _bfd_elf_create_dynamic_sections (abfd, info)
      copy relocs.  */
   if (! info->shared)
     {
-      s = bfd_make_section (abfd, bed->use_rela_p ? ".rela.bss" : ".rel.bss");
+      s = bfd_make_section (abfd, 
+                           (bed->default_use_rela_p 
+                            ? ".rela.bss" : ".rel.bss")); 
       if (s == NULL
          || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
-         || ! bfd_set_section_alignment (abfd, s, 2))
+         || ! bfd_set_section_alignment (abfd, s, ptralign))
        return false;
     }
 
   return true;
 }
+\f
 
 /* Record a new dynamic symbol.  We record the dynamic symbols as we
    read the input files, since we need to have a list of all of them
@@ -180,6 +210,10 @@ _bfd_elf_link_record_dynamic_symbol (info, h)
   if (h->dynindx == -1)
     {
       struct bfd_strtab_hash *dynstr;
+      char *p, *alc;
+      const char *name;
+      boolean copy;
+      bfd_size_type indx;
 
       h->dynindx = elf_hash_table (info)->dynsymcount;
       ++elf_hash_table (info)->dynsymcount;
@@ -193,10 +227,284 @@ _bfd_elf_link_record_dynamic_symbol (info, h)
            return false;
        }
 
-      h->dynstr_index = ((unsigned long)
-                        _bfd_stringtab_add (dynstr, h->root.root.string,
-                                            true, false));
-      if (h->dynstr_index == (unsigned long) -1)
+      /* We don't put any version information in the dynamic string
+         table.  */
+      name = h->root.root.string;
+      p = strchr (name, ELF_VER_CHR);
+      if (p == NULL)
+       {
+         alc = NULL;
+         copy = false;
+       }
+      else
+       {
+         alc = bfd_malloc (p - name + 1);
+         if (alc == NULL)
+           return false;
+         strncpy (alc, name, p - name);
+         alc[p - name] = '\0';
+         name = alc;
+         copy = true;
+       }
+
+      indx = _bfd_stringtab_add (dynstr, name, true, copy);
+
+      if (alc != NULL)
+       free (alc);
+
+      if (indx == (bfd_size_type) -1)
+       return false;
+      h->dynstr_index = indx;
+    }
+
+  return true;
+}
+
+/* Return the dynindex of a local dynamic symbol.  */
+
+long
+_bfd_elf_link_lookup_local_dynindx (info, input_bfd, input_indx)
+     struct bfd_link_info *info;
+     bfd *input_bfd;
+     long input_indx;
+{
+  struct elf_link_local_dynamic_entry *e;
+
+  for (e = elf_hash_table (info)->dynlocal; e ; e = e->next)
+    if (e->input_bfd == input_bfd && e->input_indx == input_indx)
+      return e->dynindx;
+  return -1;
+}
+
+/* This function is used to renumber the dynamic symbols, if some of
+   them are removed because they are marked as local.  This is called
+   via elf_link_hash_traverse.  */
+
+static boolean elf_link_renumber_hash_table_dynsyms
+  PARAMS ((struct elf_link_hash_entry *, PTR));
+
+static boolean
+elf_link_renumber_hash_table_dynsyms (h, data)
+     struct elf_link_hash_entry *h;
+     PTR data;
+{
+  size_t *count = (size_t *) data;
+
+  if (h->dynindx != -1)
+    h->dynindx = ++(*count);
+
+  return true;
+}
+
+/* Assign dynsym indicies.  In a shared library we generate a section
+   symbol for each output section, which come first.  Next come all of
+   the back-end allocated local dynamic syms, followed by the rest of
+   the global symbols.  */
+
+unsigned long
+_bfd_elf_link_renumber_dynsyms (output_bfd, info)
+     bfd *output_bfd;
+     struct bfd_link_info *info;
+{
+  unsigned long dynsymcount = 0;
+
+  if (info->shared)
+    {
+      asection *p;
+      for (p = output_bfd->sections; p ; p = p->next)
+       elf_section_data (p)->dynindx = ++dynsymcount;
+    }
+
+  if (elf_hash_table (info)->dynlocal)
+    {
+      struct elf_link_local_dynamic_entry *p;
+      for (p = elf_hash_table (info)->dynlocal; p ; p = p->next)
+       p->dynindx = ++dynsymcount;
+    }
+
+  elf_link_hash_traverse (elf_hash_table (info),
+                         elf_link_renumber_hash_table_dynsyms,
+                         &dynsymcount);
+
+  /* There is an unused NULL entry at the head of the table which
+     we must account for in our count.  Unless there weren't any
+     symbols, which means we'll have no table at all.  */
+  if (dynsymcount != 0)
+    ++dynsymcount;
+
+  return elf_hash_table (info)->dynsymcount = dynsymcount;
+}
+\f
+/* Create a special linker section, or return a pointer to a linker
+   section already created */
+
+elf_linker_section_t *
+_bfd_elf_create_linker_section (abfd, info, which, defaults)
+     bfd *abfd;
+     struct bfd_link_info *info;
+     enum elf_linker_section_enum which;
+     elf_linker_section_t *defaults;
+{
+  bfd *dynobj = elf_hash_table (info)->dynobj;
+  elf_linker_section_t *lsect;
+
+  /* Record the first bfd section that needs the special section */
+  if (!dynobj)
+    dynobj = elf_hash_table (info)->dynobj = abfd;
+
+  /* If this is the first time, create the section */
+  lsect = elf_linker_section (dynobj, which);
+  if (!lsect)
+    {
+      asection *s;
+
+      lsect = (elf_linker_section_t *)
+       bfd_alloc (dynobj, sizeof (elf_linker_section_t));
+
+      *lsect = *defaults;
+      elf_linker_section (dynobj, which) = lsect;
+      lsect->which = which;
+      lsect->hole_written_p = false;
+
+      /* See if the sections already exist */
+      lsect->section = s = bfd_get_section_by_name (dynobj, lsect->name);
+      if (!s || (s->flags & defaults->flags) != defaults->flags)
+       {
+         lsect->section = s = bfd_make_section_anyway (dynobj, lsect->name);
+
+         if (s == NULL)
+           return (elf_linker_section_t *)0;
+
+         bfd_set_section_flags (dynobj, s, defaults->flags);
+         bfd_set_section_alignment (dynobj, s, lsect->alignment);
+       }
+      else if (bfd_get_section_alignment (dynobj, s) < lsect->alignment)
+       bfd_set_section_alignment (dynobj, s, lsect->alignment);
+
+      s->_raw_size = align_power (s->_raw_size, lsect->alignment);
+
+      /* Is there a hole we have to provide?  If so check whether the segment is
+        too big already */
+      if (lsect->hole_size)
+       {
+         lsect->hole_offset = s->_raw_size;
+         s->_raw_size += lsect->hole_size;
+         if (lsect->hole_offset > lsect->max_hole_offset)
+           {
+             (*_bfd_error_handler) (_("%s: Section %s is already to large to put hole of %ld bytes in"),
+                                    bfd_get_filename (abfd),
+                                    lsect->name,
+                                    (long)lsect->hole_size);
+
+             bfd_set_error (bfd_error_bad_value);
+             return (elf_linker_section_t *)0;
+           }
+       }
+
+#ifdef DEBUG
+      fprintf (stderr, "Creating section %s, current size = %ld\n",
+              lsect->name, (long)s->_raw_size);
+#endif
+
+      if (lsect->sym_name)
+       {
+         struct elf_link_hash_entry *h = NULL;
+#ifdef DEBUG
+         fprintf (stderr, "Adding %s to section %s\n",
+                  lsect->sym_name,
+                  lsect->name);
+#endif
+         h = (struct elf_link_hash_entry *)
+           bfd_link_hash_lookup (info->hash, lsect->sym_name, false, false, false);
+
+         if ((h == NULL || h->root.type == bfd_link_hash_undefined)
+             && !(_bfd_generic_link_add_one_symbol (info,
+                                                    abfd,
+                                                    lsect->sym_name,
+                                                    BSF_GLOBAL,
+                                                    s,
+                                                    ((lsect->hole_size)
+                                                     ? s->_raw_size - lsect->hole_size + lsect->sym_offset
+                                                     : lsect->sym_offset),
+                                                    (const char *) NULL,
+                                                    false,
+                                                    get_elf_backend_data (abfd)->collect,
+                                                    (struct bfd_link_hash_entry **) &h)))
+           return (elf_linker_section_t *)0;
+
+         if ((defaults->which != LINKER_SECTION_SDATA)
+             && (defaults->which != LINKER_SECTION_SDATA2))
+           h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_DYNAMIC;
+
+         h->type = STT_OBJECT;
+         lsect->sym_hash = h;
+
+         if (info->shared
+             && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+           return (elf_linker_section_t *)0;
+       }
+    }
+
+#if 0
+  /* This does not make sense.  The sections which may exist in the
+     object file have nothing to do with the sections we want to
+     create.  */
+
+  /* Find the related sections if they have been created */
+  if (lsect->bss_name && !lsect->bss_section)
+    lsect->bss_section = bfd_get_section_by_name (dynobj, lsect->bss_name);
+
+  if (lsect->rel_name && !lsect->rel_section)
+    lsect->rel_section = bfd_get_section_by_name (dynobj, lsect->rel_name);
+#endif
+
+  return lsect;
+}
+
+\f
+/* Find a linker generated pointer with a given addend and type.  */
+
+elf_linker_section_pointers_t *
+_bfd_elf_find_pointer_linker_section (linker_pointers, addend, which)
+     elf_linker_section_pointers_t *linker_pointers;
+     bfd_signed_vma addend;
+     elf_linker_section_enum_t which;
+{
+  for ( ; linker_pointers != NULL; linker_pointers = linker_pointers->next)
+    {
+      if (which == linker_pointers->which && addend == linker_pointers->addend)
+       return linker_pointers;
+    }
+
+  return (elf_linker_section_pointers_t *)0;
+}
+
+\f
+/* Make the .rela section corresponding to the generated linker section.  */
+
+boolean
+_bfd_elf_make_linker_section_rela (dynobj, lsect, alignment)
+     bfd *dynobj;
+     elf_linker_section_t *lsect;
+     int alignment;
+{
+  if (lsect->rel_section)
+    return true;
+
+  lsect->rel_section = bfd_get_section_by_name (dynobj, lsect->rel_name);
+  if (lsect->rel_section == NULL)
+    {
+      lsect->rel_section = bfd_make_section (dynobj, lsect->rel_name);
+      if (lsect->rel_section == NULL
+         || ! bfd_set_section_flags (dynobj,
+                                     lsect->rel_section,
+                                     (SEC_ALLOC
+                                      | SEC_LOAD
+                                      | SEC_HAS_CONTENTS
+                                      | SEC_IN_MEMORY
+                                      | SEC_LINKER_CREATED
+                                      | SEC_READONLY))
+         || ! bfd_set_section_alignment (dynobj, lsect->rel_section, alignment))
        return false;
     }
 
This page took 0.045318 seconds and 4 git commands to generate.