* elf-bfd.h (struct elf_link_local_dynamic_entry): New.
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 4f7facf93dbe150ceb5cfbe0fc5bc82eaf9d450e..93155b11af79a45b47e5254697eb4e821183103c 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF linking support for BFD.
-   Copyright 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.
 
@@ -33,18 +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;
 
+  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)
@@ -52,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;
     }
 
@@ -62,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;
@@ -75,8 +83,8 @@ _bfd_elf_create_got_section (abfd, info)
 
   elf_hash_table (info)->hgot = h;
 
-  /* The first three global offset table entries are reserved.  */
-  s->_raw_size += 3 * 4;
+  /* The first bit of the global offset table is the header.  */
+  s->_raw_size += bed->got_header_size + bed->got_symbol_offset;
 
   return true;
 }
@@ -89,9 +97,17 @@ _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.  */
@@ -99,12 +115,17 @@ _bfd_elf_create_dynamic_sections (abfd, info)
   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)
@@ -126,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))
@@ -159,10 +181,12 @@ _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;
     }
 
@@ -186,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;
@@ -199,17 +227,116 @@ _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  */
+/* 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)
@@ -264,7 +391,7 @@ _bfd_elf_create_linker_section (abfd, info, which, defaults)
          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_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);
@@ -318,12 +445,18 @@ _bfd_elf_create_linker_section (abfd, info, which, defaults)
        }
     }
 
+#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;
 }
This page took 0.04227 seconds and 4 git commands to generate.