Don't check relocations in excluded sections
[binutils-gdb.git] / bfd / elflink.c
index ac03ce5003adea4a8fef6481e638c02a7d85d177..b432384bd7d93a2f442269506a15a3f440a189dc 100644 (file)
@@ -525,8 +525,10 @@ bfd_elf_link_mark_dynamic_symbol (struct bfd_link_info *info,
 
   if ((info->dynamic_data
        && (h->type == STT_OBJECT
+          || h->type == STT_COMMON
           || (sym != NULL
-              && ELF_ST_TYPE (sym->st_info) == STT_OBJECT)))
+              && (ELF_ST_TYPE (sym->st_info) == STT_OBJECT
+                  || ELF_ST_TYPE (sym->st_info) == STT_COMMON))))
       || (d != NULL
          && h->root.type == bfd_link_hash_new
          && (*d->match) (&d->head, NULL, h->root.root.string)))
@@ -555,6 +557,19 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
   if (h == NULL)
     return provide;
 
+  if (h->versioned == unknown)
+    {
+      /* Set versioned if symbol version is unknown.  */
+      char *version = strrchr (name, ELF_VER_CHR);
+      if (version)
+       {
+         if (version > name && version[-1] != ELF_VER_CHR)
+           h->versioned = versioned_hidden;
+         else
+           h->versioned = versioned;
+       }
+    }
+
   switch (h->root.type)
     {
     case bfd_link_hash_defined:
@@ -632,9 +647,8 @@ bfd_elf_record_link_assignment (bfd *output_bfd,
 
   if ((h->def_dynamic
        || h->ref_dynamic
-       || bfd_link_pic (info)
-       || (bfd_link_pde (info)
-          && elf_hash_table (info)->is_relocatable_executable))
+       || bfd_link_dll (info)
+       || elf_hash_table (info)->is_relocatable_executable)
       && h->dynindx == -1)
     {
       if (! bfd_elf_link_record_dynamic_symbol (info, h))
@@ -875,9 +889,9 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd,
                          &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)
+     we must account for in our count.  We always create the dynsym
+     section, even if it is empty, with dynamic sections.  */
+  if (elf_hash_table (info)->dynamic_sections_created)
     ++dynsymcount;
 
   elf_hash_table (info)->dynsymcount = dynsymcount;
@@ -1472,13 +1486,16 @@ _bfd_elf_merge_symbol (bfd *abfd,
      represent variables; this can cause confusion in principle, but
      any such confusion would seem to indicate an erroneous program or
      shared library.  We also permit a common symbol in a regular
-     object to override a weak symbol in a shared object.  */
+     object to override a weak symbol in a shared object.  A common
+     symbol in executable also overrides a symbol in a shared object.  */
 
   if (newdyn
       && newdef
       && (olddef
          || (h->root.type == bfd_link_hash_common
-             && (newweak || newfunc))))
+             && (newweak
+                 || newfunc
+                 || (!olddyn && bfd_link_executable (info))))))
     {
       *override = TRUE;
       newdef = FALSE;
@@ -3228,12 +3245,26 @@ elf_add_dt_needed_tag (bfd *abfd,
   return 0;
 }
 
+/* Return true if SONAME is on the needed list between NEEDED and STOP
+   (or the end of list if STOP is NULL), and needed by a library that
+   will be loaded.  */
+
 static bfd_boolean
-on_needed_list (const char *soname, struct bfd_link_needed_list *needed)
-{
-  for (; needed != NULL; needed = needed->next)
-    if ((elf_dyn_lib_class (needed->by) & DYN_AS_NEEDED) == 0
-       && strcmp (soname, needed->name) == 0)
+on_needed_list (const char *soname,
+               struct bfd_link_needed_list *needed,
+               struct bfd_link_needed_list *stop)
+{
+  struct bfd_link_needed_list *look;
+  for (look = needed; look != stop; look = look->next)
+    if (strcmp (soname, look->name) == 0
+       && ((elf_dyn_lib_class (look->by) & DYN_AS_NEEDED) == 0
+           /* If needed by a library that itself is not directly
+              needed, recursively check whether that library is
+              indirectly needed.  Since we add DT_NEEDED entries to
+              the end of the list, library dependencies appear after
+              the library.  Therefore search prior to the current
+              LOOK, preventing possible infinite recursion.  */
+           || on_needed_list (elf_dt_name (look->by), needed, look)))
       return TRUE;
 
   return FALSE;
@@ -3449,6 +3480,71 @@ _bfd_elf_notice_as_needed (bfd *ibfd,
   return (*info->callbacks->notice) (info, NULL, NULL, ibfd, NULL, act, 0);
 }
 
+/* Check relocations an ELF object file.  */
+
+bfd_boolean
+_bfd_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
+{
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  struct elf_link_hash_table *htab = elf_hash_table (info);
+
+  /* If this object is the same format as the output object, and it is
+     not a shared library, then let the backend look through the
+     relocs.
+
+     This is required to build global offset table entries and to
+     arrange for dynamic relocs.  It is not required for the
+     particular common case of linking non PIC code, even when linking
+     against shared libraries, but unfortunately there is no way of
+     knowing whether an object file has been compiled PIC or not.
+     Looking through the relocs is not particularly time consuming.
+     The problem is that we must either (1) keep the relocs in memory,
+     which causes the linker to require additional runtime memory or
+     (2) read the relocs twice from the input file, which wastes time.
+     This would be a good case for using mmap.
+
+     I have no idea how to handle linking PIC code into a file of a
+     different format.  It probably can't be done.  */
+  if ((abfd->flags & DYNAMIC) == 0
+      && is_elf_hash_table (htab)
+      && bed->check_relocs != NULL
+      && elf_object_id (abfd) == elf_hash_table_id (htab)
+      && (*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
+    {
+      asection *o;
+
+      for (o = abfd->sections; o != NULL; o = o->next)
+       {
+         Elf_Internal_Rela *internal_relocs;
+         bfd_boolean ok;
+
+         /* Don't check relocations in excluded sections.  */
+         if ((o->flags & SEC_RELOC) == 0
+             || (o->flags & SEC_EXCLUDE) != 0
+             || o->reloc_count == 0
+             || ((info->strip == strip_all || info->strip == strip_debugger)
+                 && (o->flags & SEC_DEBUGGING) != 0)
+             || bfd_is_abs_section (o->output_section))
+           continue;
+
+         internal_relocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL,
+                                                      info->keep_memory);
+         if (internal_relocs == NULL)
+           return FALSE;
+
+         ok = (*bed->check_relocs) (abfd, info, o, internal_relocs);
+
+         if (elf_section_data (o)->relocs != internal_relocs)
+           free (internal_relocs);
+
+         if (! ok)
+           return FALSE;
+       }
+    }
+
+  return TRUE;
+}
+
 /* Add symbols from an ELF object file to the linker hash table.  */
 
 static bfd_boolean
@@ -3598,11 +3694,14 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       /* If we are creating a shared library, create all the dynamic
         sections immediately.  We need to attach them to something,
         so we attach them to this BFD, provided it is the right
-        format and is not from ld --just-symbols.  FIXME: If there
+        format and is not from ld --just-symbols.  Always create the
+        dynamic sections for -E/--dynamic-list.  FIXME: If there
         are no input BFD's of the same format as the output, we can't
         make a shared library.  */
       if (!just_syms
-         && bfd_link_pic (info)
+         && (bfd_link_pic (info)
+             || (!bfd_link_relocatable (info)
+                 && (info->export_dynamic || info->dynamic)))
          && is_elf_hash_table (htab)
          && info->output_bfd->xvec == abfd->xvec
          && !htab->dynamic_sections_created)
@@ -4549,7 +4648,7 @@ error_free_dyn:
                    goto error_free_vers;
                }
            }
-         else if (dynsym && h->dynindx != -1)
+         else if (h->dynindx != -1)
            /* If the symbol already has a dynamic index, but
               visibility says it should not be visible, turn it into
               a local symbol.  */
@@ -4573,7 +4672,8 @@ error_free_dyn:
                       || (old_bfd->flags & BFD_PLUGIN) == 0))
                  || (h->ref_dynamic_nonweak
                      && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0
-                     && !on_needed_list (elf_dt_name (abfd), htab->needed))))
+                     && !on_needed_list (elf_dt_name (abfd),
+                                         htab->needed, NULL))))
            {
              int ret;
              const char *soname = elf_dt_name (abfd);
@@ -4915,57 +5015,9 @@ error_free_dyn:
       && !(*bed->check_directives) (abfd, info))
     return FALSE;
 
-  /* If this object is the same format as the output object, and it is
-     not a shared library, then let the backend look through the
-     relocs.
-
-     This is required to build global offset table entries and to
-     arrange for dynamic relocs.  It is not required for the
-     particular common case of linking non PIC code, even when linking
-     against shared libraries, but unfortunately there is no way of
-     knowing whether an object file has been compiled PIC or not.
-     Looking through the relocs is not particularly time consuming.
-     The problem is that we must either (1) keep the relocs in memory,
-     which causes the linker to require additional runtime memory or
-     (2) read the relocs twice from the input file, which wastes time.
-     This would be a good case for using mmap.
-
-     I have no idea how to handle linking PIC code into a file of a
-     different format.  It probably can't be done.  */
-  if (! dynamic
-      && is_elf_hash_table (htab)
-      && bed->check_relocs != NULL
-      && elf_object_id (abfd) == elf_hash_table_id (htab)
-      && (*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
-    {
-      asection *o;
-
-      for (o = abfd->sections; o != NULL; o = o->next)
-       {
-         Elf_Internal_Rela *internal_relocs;
-         bfd_boolean ok;
-
-         if ((o->flags & SEC_RELOC) == 0
-             || o->reloc_count == 0
-             || ((info->strip == strip_all || info->strip == strip_debugger)
-                 && (o->flags & SEC_DEBUGGING) != 0)
-             || bfd_is_abs_section (o->output_section))
-           continue;
-
-         internal_relocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL,
-                                                      info->keep_memory);
-         if (internal_relocs == NULL)
-           goto error_return;
-
-         ok = (*bed->check_relocs) (abfd, info, o, internal_relocs);
-
-         if (elf_section_data (o)->relocs != internal_relocs)
-           free (internal_relocs);
-
-         if (! ok)
-           goto error_return;
-       }
-    }
+  if (!info->check_relocs_after_open_input
+      && !_bfd_elf_link_check_relocs (abfd, info))
+    return FALSE;
 
   /* If this is a non-traditional link, try to optimize the handling
      of the .stab/.stabstr sections.  */
@@ -7731,10 +7783,15 @@ resolve_symbol (const char *name,
   return FALSE;
 }
 
+/* Looks up NAME in SECTIONS.  If found sets RESULT to NAME's address (in
+   bytes) and returns TRUE, otherwise returns FALSE.  Accepts pseudo-section
+   names like "foo.end" which is the end address of section "foo".  */
+   
 static bfd_boolean
 resolve_section (const char *name,
                 asection *sections,
-                bfd_vma *result)
+                bfd_vma *result,
+                bfd * abfd)
 {
   asection *curr;
   unsigned int len;
@@ -7747,6 +7804,7 @@ resolve_section (const char *name,
       }
 
   /* Hmm. still haven't found it. try pseudo-section names.  */
+  /* FIXME: This could be coded more efficiently...  */
   for (curr = sections; curr; curr = curr->next)
     {
       len = strlen (curr->name);
@@ -7757,7 +7815,7 @@ resolve_section (const char *name,
        {
          if (strncmp (".end", name + len, 4) == 0)
            {
-             *result = curr->vma + curr->size;
+             *result = curr->vma + curr->size / bfd_octets_per_byte (abfd);
              return TRUE;
            }
 
@@ -7839,7 +7897,7 @@ eval_symbol (bfd_vma *result,
 
       if (symbol_is_section)
        {
-         if (!resolve_section (symbuf, flinfo->output_bfd->sections, result)
+         if (!resolve_section (symbuf, flinfo->output_bfd->sections, result, input_bfd)
              && !resolve_symbol (symbuf, input_bfd, flinfo, result,
                                  isymbuf, locsymcount))
            {
@@ -7852,7 +7910,7 @@ eval_symbol (bfd_vma *result,
          if (!resolve_symbol (symbuf, input_bfd, flinfo, result,
                               isymbuf, locsymcount)
              && !resolve_section (symbuf, flinfo->output_bfd->sections,
-                                  result))
+                                  result, input_bfd))
            {
              undefined_reference ("symbol", symbuf);
              return FALSE;
@@ -8076,8 +8134,8 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd,
   else
     shift = (8 * wordsz) - (start + len);
 
-  /* FIXME: octets_per_byte.  */
-  x = get_value (wordsz, chunksz, input_bfd, contents + rel->r_offset);
+  x = get_value (wordsz, chunksz, input_bfd,
+                contents + rel->r_offset * bfd_octets_per_byte (input_bfd));
 
 #ifdef DEBUG
   printf ("Doing complex reloc: "
@@ -8109,8 +8167,8 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd,
          (unsigned long) relocation, (unsigned long) (mask << shift),
          (unsigned long) ((relocation & mask) << shift), (unsigned long) x);
 #endif
-  /* FIXME: octets_per_byte.  */
-  put_value (wordsz, chunksz, input_bfd, x, contents + rel->r_offset);
+  put_value (wordsz, chunksz, input_bfd, x,
+            contents + rel->r_offset * bfd_octets_per_byte (input_bfd));
   return r;
 }
 
@@ -9023,6 +9081,28 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
   return FALSE;
 }
 
+/* Convert ELF common symbol TYPE.  */
+
+static int
+elf_link_convert_common_type (struct bfd_link_info *info, int type)
+{
+  /* Commom symbol can only appear in relocatable link.  */
+  if (!bfd_link_relocatable (info))
+    abort ();
+  switch (info->elf_stt_common)
+    {
+    case unchanged:
+      break;
+    case elf_stt_common:
+      type = STT_COMMON;
+      break;
+    case no_elf_stt_common:
+      type = STT_OBJECT;
+      break;
+    }
+  return type;
+}
+
 /* Add an external symbol to the symbol table.  This is called from
    the hash table traversal routine.  When generating a shared object,
    we go through the symbol table twice.  The first time we output
@@ -9042,6 +9122,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
   const struct elf_backend_data *bed;
   long indx;
   int ret;
+  unsigned int type;
   /* A symbol is bound locally if it is forced local or it is locally
      defined, hidden versioned, not referenced by shared library and
      not exported when linking executable.  */
@@ -9176,35 +9257,21 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
           && (h->root.u.undef.abfd->flags & BFD_PLUGIN) != 0)
     strip = TRUE;
 
+  type = h->type;
+
   /* If we're stripping it, and it's not a dynamic symbol, there's
      nothing else to do.   However, if it is a forced local symbol or
      an ifunc symbol we need to give the backend finish_dynamic_symbol
      function a chance to make it dynamic.  */
   if (strip
       && h->dynindx == -1
-      && h->type != STT_GNU_IFUNC
+      && type != STT_GNU_IFUNC
       && !h->forced_local)
     return TRUE;
 
   sym.st_value = 0;
   sym.st_size = h->size;
   sym.st_other = h->other;
-  if (local_bind)
-    {
-      sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type);
-      /* Turn off visibility on local symbol.  */
-      sym.st_other &= ~ELF_ST_VISIBILITY (-1);
-    }
-  /* Set STB_GNU_UNIQUE only if symbol is defined in regular object.  */
-  else if (h->unique_global && h->def_regular)
-    sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, h->type);
-  else if (h->root.type == bfd_link_hash_undefweak
-          || h->root.type == bfd_link_hash_defweak)
-    sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
-  else
-    sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type);
-  sym.st_target_internal = h->target_internal;
-
   switch (h->root.type)
     {
     default:
@@ -9279,6 +9346,42 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
       return TRUE;
     }
 
+  if (type == STT_COMMON || type == STT_OBJECT)
+    switch (h->root.type)
+      {
+      case bfd_link_hash_common:
+       type = elf_link_convert_common_type (flinfo->info, type);
+       break;
+      case bfd_link_hash_defined:
+      case bfd_link_hash_defweak:
+       if (bed->common_definition (&sym))
+         type = elf_link_convert_common_type (flinfo->info, type);
+       else
+         type = STT_OBJECT;
+       break;
+      case bfd_link_hash_undefined:
+      case bfd_link_hash_undefweak:
+       break;
+      default:
+       abort ();
+      }
+
+  if (local_bind)
+    {
+      sym.st_info = ELF_ST_INFO (STB_LOCAL, type);
+      /* Turn off visibility on local symbol.  */
+      sym.st_other &= ~ELF_ST_VISIBILITY (-1);
+    }
+  /* Set STB_GNU_UNIQUE only if symbol is defined in regular object.  */
+  else if (h->unique_global && h->def_regular)
+    sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, type);
+  else if (h->root.type == bfd_link_hash_undefweak
+          || h->root.type == bfd_link_hash_defweak)
+    sym.st_info = ELF_ST_INFO (STB_WEAK, type);
+  else
+    sym.st_info = ELF_ST_INFO (STB_GLOBAL, type);
+  sym.st_target_internal = h->target_internal;
+
   /* Give the processor backend a chance to tweak the symbol value,
      and also to finish up anything that needs to be done for this
      symbol.  FIXME: Not calling elf_backend_finish_dynamic_symbol for
@@ -9315,7 +9418,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
          || ELF_ST_BIND (sym.st_info) == STB_WEAK))
     {
       int bindtype;
-      unsigned int type = ELF_ST_TYPE (sym.st_info);
+      type = ELF_ST_TYPE (sym.st_info);
 
       /* Turn an undefined IFUNC symbol into a normal FUNC symbol. */
       if (type == STT_GNU_IFUNC)
@@ -10470,11 +10573,13 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
          break;
        default:
          {
-           /* FIXME: octets_per_byte.  */
            if (! (o->flags & SEC_EXCLUDE))
              {
                file_ptr offset = (file_ptr) o->output_offset;
                bfd_size_type todo = o->size;
+
+               offset *= bfd_octets_per_byte (output_bfd);
+
                if ((o->flags & SEC_ELF_REVERSE_COPY))
                  {
                    /* Reverse-copy input section to output.  */
@@ -10638,8 +10743,11 @@ elf_reloc_link_order (bfd *output_bfd,
            }
          break;
        }
+
       ok = bfd_set_section_contents (output_bfd, output_section, buf,
-                                    link_order->offset, size);
+                                    link_order->offset
+                                    * bfd_octets_per_byte (output_bfd),
+                                    size);
       free (buf);
       if (! ok)
        return FALSE;
@@ -10821,9 +10929,8 @@ elf_fixup_link_order (bfd *abfd, asection *o)
     {
       s = sections[n]->u.indirect.section;
       offset &= ~(bfd_vma) 0 << s->alignment_power;
-      s->output_offset = offset;
+      s->output_offset = offset / bfd_octets_per_byte (abfd);
       sections[n]->offset = offset;
-      /* FIXME: octets_per_byte.  */
       offset += sections[n]->size;
     }
 
@@ -11615,7 +11722,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
       /* sh_name was set in prep_headers.  */
       symstrtab_hdr->sh_type = SHT_STRTAB;
-      symstrtab_hdr->sh_flags = 0;
+      symstrtab_hdr->sh_flags = bed->elf_strtab_flags;
       symstrtab_hdr->sh_addr = 0;
       symstrtab_hdr->sh_size = _bfd_elf_strtab_size (flinfo.symstrtab);
       symstrtab_hdr->sh_entsize = 0;
@@ -11883,10 +11990,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
            continue;
          if (strcmp (o->name, ".dynstr") != 0)
            {
-             /* FIXME: octets_per_byte.  */
              if (! bfd_set_section_contents (abfd, o->output_section,
                                              o->contents,
-                                             (file_ptr) o->output_offset,
+                                             (file_ptr) o->output_offset
+                                             * bfd_octets_per_byte (abfd),
                                              o->size))
                goto error_return;
            }