Fix indentation (and clang warning) in c-lang.c
[deliverable/binutils-gdb.git] / bfd / elf-vxworks.c
index 90e620a905592f47a7a3421ca4c874d20e559a24..8fe17bf628fdea9be2c49c4017758bbbca26d2f6 100644 (file)
@@ -1,11 +1,11 @@
 /* VxWorks support for ELF
-   Copyright 2005 Free Software Foundation, Inc.
+   Copyright (C) 2005-2019 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
    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
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* This file provides routines used by all VxWorks targets.  */
 
-#include "bfd.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "elf-vxworks.h"
+#include "elf/vxworks.h"
+
+/* Return true if symbol NAME, as defined by ABFD, is one of the special
+   __GOTT_BASE__ or __GOTT_INDEX__ symbols.  */
+
+static bfd_boolean
+elf_vxworks_gott_symbol_p (bfd *abfd, const char *name)
+{
+  char leading;
+
+  leading = bfd_get_symbol_leading_char (abfd);
+  if (leading)
+    {
+      if (*name != leading)
+       return FALSE;
+      name++;
+    }
+  return (strcmp (name, "__GOTT_BASE__") == 0
+         || strcmp (name, "__GOTT_INDEX__") == 0);
+}
 
 /* Tweak magic VxWorks symbols as they are loaded.  */
 bfd_boolean
-elf_vxworks_add_symbol_hook (bfd *abfd ATTRIBUTE_UNUSED,
+elf_vxworks_add_symbol_hook (bfd *abfd,
                             struct bfd_link_info *info,
                             Elf_Internal_Sym *sym,
                             const char **namep,
@@ -44,9 +62,8 @@ elf_vxworks_add_symbol_hook (bfd *abfd ATTRIBUTE_UNUSED,
      give the symbol weak binding to get the desired samantics.
      This transformation will be undone in
      elf_i386_vxworks_link_output_symbol_hook. */
-  if ((info->shared || abfd->flags & DYNAMIC)
-      && (strcmp (*namep, "__GOTT_INDEX__") == 0
-         || strcmp (*namep, "__GOTT_BASE__") == 0))
+  if ((bfd_link_pic (info) || abfd->flags & DYNAMIC)
+      && elf_vxworks_gott_symbol_p (abfd, *namep))
     {
       sym->st_info = ELF_ST_INFO (STB_WEAK, ELF_ST_TYPE (sym->st_info));
       *flagsp |= BSF_WEAK;
@@ -70,16 +87,17 @@ elf_vxworks_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info,
   htab = elf_hash_table (info);
   bed = get_elf_backend_data (dynobj);
 
-  if (!info->shared)
+  if (!bfd_link_pic (info))
     {
-      s = bfd_make_section_with_flags (dynobj,
-                                      bed->default_use_rela_p
-                                      ? ".rela.plt.unloaded"
-                                      : ".rel.plt.unloaded",
-                                      SEC_HAS_CONTENTS | SEC_IN_MEMORY
-                                      | SEC_READONLY | SEC_LINKER_CREATED);
+      s = bfd_make_section_anyway_with_flags (dynobj,
+                                             bed->default_use_rela_p
+                                             ? ".rela.plt.unloaded"
+                                             : ".rel.plt.unloaded",
+                                             SEC_HAS_CONTENTS | SEC_IN_MEMORY
+                                             | SEC_READONLY
+                                             | SEC_LINKER_CREATED);
       if (s == NULL
-         || !bfd_set_section_alignment (dynobj, s, bed->s->log_file_align))
+         || !bfd_set_section_alignment (s, bed->s->log_file_align))
        return FALSE;
 
       *srelplt2_out = s;
@@ -108,29 +126,24 @@ elf_vxworks_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info,
 }
 
 /* Tweak magic VxWorks symbols as they are written to the output file.  */
-bfd_boolean
+int
 elf_vxworks_link_output_symbol_hook (struct bfd_link_info *info
                                       ATTRIBUTE_UNUSED,
                                     const char *name,
                                     Elf_Internal_Sym *sym,
                                     asection *input_sec ATTRIBUTE_UNUSED,
-                                    struct elf_link_hash_entry *h
-                                      ATTRIBUTE_UNUSED)
+                                    struct elf_link_hash_entry *h)
 {
-  /* Ignore the first dummy symbol.  */
-  if (!name)
-    return TRUE;
-
   /* Reverse the effects of the hack in elf_vxworks_add_symbol_hook.  */
-  if (strcmp (name, "__GOTT_INDEX__") == 0
-      || strcmp (name, "__GOTT_BASE__") == 0)
+  if (h
+      && h->root.type == bfd_link_hash_undefweak
+      && elf_vxworks_gott_symbol_p (h->root.u.undef.abfd, name))
     sym->st_info = ELF_ST_INFO (STB_GLOBAL, ELF_ST_TYPE (sym->st_info));
 
-  return TRUE;
+  return 1;
 }
 
-
-/* Copy relocations into the output file.  Fixes up relocations againt PLT
+/* Copy relocations into the output file.  Fixes up relocations against PLT
    entries, then calls the generic routine.  */
 
 bfd_boolean
@@ -141,49 +154,55 @@ elf_vxworks_emit_relocs (bfd *output_bfd,
                         struct elf_link_hash_entry **rel_hash)
 {
   const struct elf_backend_data *bed;
-  Elf_Internal_Rela *irela;
-  Elf_Internal_Rela *irelaend;
   int j;
 
   bed = get_elf_backend_data (output_bfd);
 
-  irela = internal_relocs;
-  irelaend = irela + (NUM_SHDR_ENTRIES (input_rel_hdr)
-                     * bed->s->int_rels_per_ext_rel);
-  while (irela < irelaend)
+  if (output_bfd->flags & (DYNAMIC|EXEC_P))
     {
-      if ((output_bfd->flags & (DYNAMIC|EXEC_P))
-         && *rel_hash
-         && (*rel_hash)->def_dynamic
-         && !(*rel_hash)->def_regular
-         && (*rel_hash)->root.type == bfd_link_hash_defined
-         && (*rel_hash)->root.u.def.section->output_section != NULL)
+      Elf_Internal_Rela *irela;
+      Elf_Internal_Rela *irelaend;
+      struct elf_link_hash_entry **hash_ptr;
+
+      for (irela = internal_relocs,
+            irelaend = irela + (NUM_SHDR_ENTRIES (input_rel_hdr)
+                                * bed->s->int_rels_per_ext_rel),
+            hash_ptr = rel_hash;
+          irela < irelaend;
+          irela += bed->s->int_rels_per_ext_rel,
+            hash_ptr++)
        {
-         /* This is a relocation from an executable or shared library
-            against a symbol in a different shared library.  We are
-            creating a definition in the output file but it does not come
-            from any of our normal (.o) files. ie. a PLT stub.
-            Normally this would be a relocation against against SHN_UNDEF
-            with the VMA of the PLT stub.  This upsets the VxWorks loader.
-            Convert it to a section-relative relocation.
-            This gets some other symbols (for instance .dynbss),
-            but is conservatively correct.  */
-         for (j = 0; j < bed->s->int_rels_per_ext_rel; j++)
+         if (*hash_ptr
+             && (*hash_ptr)->def_dynamic
+             && !(*hash_ptr)->def_regular
+             && ((*hash_ptr)->root.type == bfd_link_hash_defined
+                 || (*hash_ptr)->root.type == bfd_link_hash_defweak)
+             && (*hash_ptr)->root.u.def.section->output_section != NULL)
            {
-             asection *sec = (*rel_hash)->root.u.def.section;
-             int this_idx =
-               elf_section_data (sec->output_section)->this_idx;
-
-             irela[j].r_info = ELF32_R_INFO (this_idx,
-                 ELF32_R_TYPE (irela[j].r_info));
-             irela[j].r_addend += (*rel_hash)->root.u.def.value;
-             irela[j].r_addend += sec->output_offset;
+             /* This is a relocation from an executable or shared
+                library against a symbol in a different shared
+                library.  We are creating a definition in the output
+                file but it does not come from any of our normal (.o)
+                files. ie. a PLT stub.  Normally this would be a
+                relocation against against SHN_UNDEF with the VMA of
+                the PLT stub.  This upsets the VxWorks loader.
+                Convert it to a section-relative relocation.  This
+                gets some other symbols (for instance .dynbss), but
+                is conservatively correct.  */
+             for (j = 0; j < bed->s->int_rels_per_ext_rel; j++)
+               {
+                 asection *sec = (*hash_ptr)->root.u.def.section;
+                 int this_idx = sec->output_section->target_index;
+
+                 irela[j].r_info
+                   = ELF32_R_INFO (this_idx, ELF32_R_TYPE (irela[j].r_info));
+                 irela[j].r_addend += (*hash_ptr)->root.u.def.value;
+                 irela[j].r_addend += sec->output_offset;
+               }
+             /* Stop the generic routine adjusting this entry.  */
+             *hash_ptr = NULL;
            }
-         /* Stop the generic routine adjusting this entry.  */
-         *rel_hash = NULL;
        }
-      irela += bed->s->int_rels_per_ext_rel;
-      rel_hash++;
     }
   return _bfd_elf_link_output_relocs (output_bfd, input_section,
                                      input_rel_hdr, internal_relocs,
@@ -193,9 +212,8 @@ elf_vxworks_emit_relocs (bfd *output_bfd,
 
 /* Set the sh_link and sh_info fields on the static plt relocation secton.  */
 
-void
-elf_vxworks_final_write_processing (bfd *abfd,
-                                   bfd_boolean linker ATTRIBUTE_UNUSED)
+bfd_boolean
+elf_vxworks_final_write_processing (bfd *abfd)
 {
   asection * sec;
   struct bfd_elf_section_data *d;
@@ -203,11 +221,78 @@ elf_vxworks_final_write_processing (bfd *abfd,
   sec = bfd_get_section_by_name (abfd, ".rel.plt.unloaded");
   if (!sec)
     sec = bfd_get_section_by_name (abfd, ".rela.plt.unloaded");
-  if (!sec)
-    return;
-  d = elf_section_data (sec);
-  d->this_hdr.sh_link = elf_tdata (abfd)->symtab_section;
-  sec = bfd_get_section_by_name (abfd, ".plt");
   if (sec)
-    d->this_hdr.sh_info = elf_section_data (sec)->this_idx;
+    {
+      d = elf_section_data (sec);
+      d->this_hdr.sh_link = elf_onesymtab (abfd);
+      sec = bfd_get_section_by_name (abfd, ".plt");
+      if (sec)
+       d->this_hdr.sh_info = elf_section_data (sec)->this_idx;
+    }
+  return _bfd_elf_final_write_processing (abfd);
+}
+
+/* Add the dynamic entries required by VxWorks.  These point to the
+   tls sections.  */
+
+bfd_boolean
+elf_vxworks_add_dynamic_entries (bfd *output_bfd, struct bfd_link_info *info)
+{
+  if (bfd_get_section_by_name (output_bfd, ".tls_data"))
+    {
+      if (!_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_DATA_START, 0)
+         || !_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_DATA_SIZE, 0)
+         || !_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_DATA_ALIGN, 0))
+       return FALSE;
+    }
+  if (bfd_get_section_by_name (output_bfd, ".tls_vars"))
+    {
+      if (!_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_VARS_START, 0)
+         || !_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_VARS_SIZE, 0))
+       return FALSE;
+    }
+  return TRUE;
+}
+
+/* If *DYN is one of the VxWorks-specific dynamic entries, then fill
+   in the value now  and return TRUE.  Otherwise return FALSE.  */
+
+bfd_boolean
+elf_vxworks_finish_dynamic_entry (bfd *output_bfd, Elf_Internal_Dyn *dyn)
+{
+  asection *sec;
+
+  switch (dyn->d_tag)
+    {
+    default:
+      return FALSE;
+
+    case DT_VX_WRS_TLS_DATA_START:
+      sec = bfd_get_section_by_name (output_bfd, ".tls_data");
+      dyn->d_un.d_ptr = sec->vma;
+      break;
+
+    case DT_VX_WRS_TLS_DATA_SIZE:
+      sec = bfd_get_section_by_name (output_bfd, ".tls_data");
+      dyn->d_un.d_val = sec->size;
+      break;
+
+    case DT_VX_WRS_TLS_DATA_ALIGN:
+      sec = bfd_get_section_by_name (output_bfd, ".tls_data");
+      dyn->d_un.d_val = (bfd_size_type) 1 << bfd_section_alignment (sec);
+      break;
+
+    case DT_VX_WRS_TLS_VARS_START:
+      sec = bfd_get_section_by_name (output_bfd, ".tls_vars");
+      dyn->d_un.d_ptr = sec->vma;
+      break;
+
+    case DT_VX_WRS_TLS_VARS_SIZE:
+      sec = bfd_get_section_by_name (output_bfd, ".tls_vars");
+      dyn->d_un.d_val = sec->size;
+      break;
+    }
+  return TRUE;
 }
+
+
This page took 0.032826 seconds and 4 git commands to generate.