Fix formatting
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 00e840cd3a014f9c6d54cf7882f8a133bd437326..8039b4fe35b006f8681f975549a5d8b42a8d23e3 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF linking support for BFD.
-   Copyright 1995 Free Software Foundation, Inc.
+   Copyright 1995, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -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,8 +81,10 @@ _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;
 }
@@ -86,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)
@@ -122,27 +147,30 @@ _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))
     return false;
 
-  /* The .dynbss section is a place to put symbols which are defined
-     by dynamic objects, are referenced by regular objects, and are
-     not functions.  We must allocate space for them in the process
-     image and use a R_*_COPY reloc to tell the dynamic linker to
-     initialize them at run time.  The linker script puts the .dynbss
-     section into the .bss section of the final image.  */
-  s = bfd_make_section (abfd, ".dynbss");
-  if (s == NULL
-      || ! bfd_set_section_flags (abfd, s, SEC_ALLOC))
-    return false;
+  if (bed->want_dynbss)
+    {
+      /* The .dynbss section is a place to put symbols which are defined
+        by dynamic objects, are referenced by regular objects, and are
+        not functions.  We must allocate space for them in the process
+        image and use a R_*_COPY reloc to tell the dynamic linker to
+        initialize them at run time.  The linker script puts the .dynbss
+        section into the .bss section of the final image.  */
+      s = bfd_make_section (abfd, ".dynbss");
+      if (s == NULL
+         || ! bfd_set_section_flags (abfd, s, SEC_ALLOC))
+       return false;
 
-  /* The .rel[a].bss section holds copy relocs.  This section is not
+      /* The .rel[a].bss section holds copy relocs.  This section is not
      normally needed.  We need to create it here, though, so that the
      linker will map it to an output section.  We can't just create it
      only if we need it, because we will not know whether we need it
@@ -153,13 +181,16 @@ _bfd_elf_create_dynamic_sections (abfd, info)
      be needed, we can discard it later.  We will never need this
      section when generating a shared object, since they do not use
      copy relocs.  */
-  if (! info->shared)
-    {
-      s = bfd_make_section (abfd, bed->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))
-       return false;
+      if (! info->shared)
+       {
+         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, ptralign))
+           return false;
+       }
     }
 
   return true;
@@ -182,6 +213,29 @@ _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;
+
+      /* XXX: The ABI draft says the linker must turn hidden and
+        internal symbols into STB_LOCAL symbols when producing the
+        DSO. However, if ld.so honors st_other in the dynamic table,
+        this would not be necessary.  */
+      switch (ELF_ST_VISIBILITY (h->other))
+       {
+       case STV_INTERNAL:
+       case STV_HIDDEN:
+         if (h->root.type != bfd_link_hash_undefined
+             && h->root.type != bfd_link_hash_undefweak)
+           {
+             h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
+             return true;
+           }
+
+       default:
+         break;
+       }
 
       h->dynindx = elf_hash_table (info)->dynsymcount;
       ++elf_hash_table (info)->dynsymcount;
@@ -195,17 +249,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)
@@ -226,7 +379,6 @@ _bfd_elf_create_linker_section (abfd, info, which, defaults)
   if (!lsect)
     {
       asection *s;
-      static elf_linker_section_t zero_section;
 
       lsect = (elf_linker_section_t *)
        bfd_alloc (dynobj, sizeof (elf_linker_section_t));
@@ -238,9 +390,9 @@ _bfd_elf_create_linker_section (abfd, info, which, defaults)
 
       /* See if the sections already exist */
       lsect->section = s = bfd_get_section_by_name (dynobj, lsect->name);
-      if (!s)
+      if (!s || (s->flags & defaults->flags) != defaults->flags)
        {
-         lsect->section = s = bfd_make_section (dynobj, lsect->name);
+         lsect->section = s = bfd_make_section_anyway (dynobj, lsect->name);
 
          if (s == NULL)
            return (elf_linker_section_t *)0;
@@ -261,7 +413,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);
@@ -284,21 +436,28 @@ _bfd_elf_create_linker_section (abfd, info, which, defaults)
                   lsect->sym_name,
                   lsect->name);
 #endif
-         if (!(_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)))
+         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;
 
-         h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_DYNAMIC;
+         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;
 
@@ -308,12 +467,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;
 }
@@ -359,6 +524,7 @@ _bfd_elf_make_linker_section_rela (dynobj, lsect, alignment)
                                       | SEC_LOAD
                                       | SEC_HAS_CONTENTS
                                       | SEC_IN_MEMORY
+                                      | SEC_LINKER_CREATED
                                       | SEC_READONLY))
          || ! bfd_set_section_alignment (dynobj, lsect->rel_section, alignment))
        return false;
@@ -366,4 +532,3 @@ _bfd_elf_make_linker_section_rela (dynobj, lsect, alignment)
 
   return true;
 }
-
This page took 0.054596 seconds and 4 git commands to generate.