Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 6f03c5c09fdfadd0d02de02f7632fc35aa58ecef..6624864bf540bd1bedc2c14b9950d52a33da9a21 100644 (file)
@@ -2039,7 +2039,7 @@ _bfd_elf_add_default_symbol (bfd *abfd,
   /* We also need to define an indirection from the nondefault version
      of the symbol.  */
 
-nondefault:
+ nondefault:
   len = strlen (name);
   shortname = (char *) bfd_hash_allocate (&info->hash->table, len);
   if (shortname == NULL)
@@ -3323,8 +3323,8 @@ _bfd_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
 
   elf_hash_table (info)->tls_sec = tls;
 
-  /* Ensure the alignment of the first section is the largest alignment,
-     so that the tls segment starts aligned.  */
+  /* Ensure the alignment of the first section (usually .tdata) is the largest
+     alignment, so that the tls segment starts aligned.  */
   if (tls != NULL)
     tls->alignment_power = align;
 
@@ -3501,6 +3501,104 @@ _bfd_elf_add_dynamic_entry (struct bfd_link_info *info,
   return TRUE;
 }
 
+/* Strip zero-sized dynamic sections.  */
+
+bfd_boolean
+_bfd_elf_strip_zero_sized_dynamic_sections (struct bfd_link_info *info)
+{
+  struct elf_link_hash_table *hash_table;
+  const struct elf_backend_data *bed;
+  asection *s, *sdynamic, **pp;
+  asection *rela_dyn, *rel_dyn;
+  Elf_Internal_Dyn dyn;
+  bfd_byte *extdyn, *next;
+  void (*swap_dyn_in) (bfd *, const void *, Elf_Internal_Dyn *);
+  bfd_boolean strip_zero_sized;
+  bfd_boolean strip_zero_sized_plt;
+
+  if (bfd_link_relocatable (info))
+    return TRUE;
+
+  hash_table = elf_hash_table (info);
+  if (!is_elf_hash_table (hash_table))
+    return FALSE;
+
+  if (!hash_table->dynobj)
+    return TRUE;
+
+  sdynamic= bfd_get_linker_section (hash_table->dynobj, ".dynamic");
+  if (!sdynamic)
+    return TRUE;
+
+  bed = get_elf_backend_data (hash_table->dynobj);
+  swap_dyn_in = bed->s->swap_dyn_in;
+
+  strip_zero_sized = FALSE;
+  strip_zero_sized_plt = FALSE;
+
+  /* Strip zero-sized dynamic sections.  */
+  rela_dyn = bfd_get_section_by_name (info->output_bfd, ".rela.dyn");
+  rel_dyn = bfd_get_section_by_name (info->output_bfd, ".rel.dyn");
+  for (pp = &info->output_bfd->sections; (s = *pp) != NULL;)
+    if (s->size == 0
+       && (s == rela_dyn
+           || s == rel_dyn
+           || s == hash_table->srelplt->output_section
+           || s == hash_table->splt->output_section))
+      {
+       *pp = s->next;
+       info->output_bfd->section_count--;
+       strip_zero_sized = TRUE;
+       if (s == rela_dyn)
+         s = rela_dyn;
+       if (s == rel_dyn)
+         s = rel_dyn;
+       else if (s == hash_table->splt->output_section)
+         {
+           s = hash_table->splt;
+           strip_zero_sized_plt = TRUE;
+         }
+       else
+         s = hash_table->srelplt;
+       s->flags |= SEC_EXCLUDE;
+       s->output_section = bfd_abs_section_ptr;
+      }
+    else
+      pp = &s->next;
+
+  if (strip_zero_sized_plt)
+    for (extdyn = sdynamic->contents;
+        extdyn < sdynamic->contents + sdynamic->size;
+        extdyn = next)
+      {
+       next = extdyn + bed->s->sizeof_dyn;
+       swap_dyn_in (hash_table->dynobj, extdyn, &dyn);
+       switch (dyn.d_tag)
+         {
+         default:
+           break;
+         case DT_JMPREL:
+         case DT_PLTRELSZ:
+         case DT_PLTREL:
+           /* Strip DT_PLTRELSZ, DT_JMPREL and DT_PLTREL entries if
+              the procedure linkage table (the .plt section) has been
+              removed.  */
+           memmove (extdyn, next,
+                    sdynamic->size - (next - sdynamic->contents));
+           next = extdyn;
+         }
+      }
+
+  if (strip_zero_sized)
+    {
+      /* Regenerate program headers.  */
+      elf_seg_map (info->output_bfd) = NULL;
+      return _bfd_elf_map_sections_to_segments (info->output_bfd, info);
+    }
+
+  return TRUE;
+}
+
 /* Add a DT_NEEDED entry for this dynamic object.  Returns -1 on error,
    1 if a DT_NEEDED tag already exists, and 0 on success.  */
 
@@ -4089,7 +4187,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 
          if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
            {
-error_free_dyn:
+           error_free_dyn:
              free (dynbuf);
              goto error_return;
            }
@@ -4218,10 +4316,14 @@ error_free_dyn:
        if (phdr->p_type == PT_GNU_RELRO)
          {
            for (s = abfd->sections; s != NULL; s = s->next)
-             if ((s->flags & SEC_ALLOC) != 0
-                 && s->vma >= phdr->p_vaddr
-                 && s->vma + s->size <= phdr->p_vaddr + phdr->p_memsz)
-               s->flags |= SEC_READONLY;
+             {
+               unsigned int opb = bfd_octets_per_byte (abfd, s);
+
+               if ((s->flags & SEC_ALLOC) != 0
+                   && s->vma * opb >= phdr->p_vaddr
+                   && s->vma * opb + s->size <= phdr->p_vaddr + phdr->p_memsz)
+                 s->flags |= SEC_READONLY;
+             }
            break;
          }
 
@@ -8209,7 +8311,7 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
 
   result = TRUE;
 
-done:
+ done:
   if (symtable1)
     free (symtable1);
   if (symtable2)
@@ -9882,11 +9984,13 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
          && (!h->ref_regular || flinfo->info->gc_sections)
          && !elf_link_check_versioned_symbol (flinfo->info, bed, h)
          && flinfo->info->unresolved_syms_in_shared_libs != RM_IGNORE)
-       (*flinfo->info->callbacks->undefined_symbol)
-         (flinfo->info, h->root.root.string,
-          h->ref_regular ? NULL : h->root.u.undef.abfd,
-          NULL, 0,
-          flinfo->info->unresolved_syms_in_shared_libs == RM_GENERATE_ERROR);
+       {
+         flinfo->info->callbacks->undefined_symbol
+           (flinfo->info, h->root.root.string,
+            h->ref_regular ? NULL : h->root.u.undef.abfd, NULL, 0,
+            flinfo->info->unresolved_syms_in_shared_libs == RM_DIAGNOSE
+            && !flinfo->info->warn_unresolved_syms);
+       }
 
       /* Strip a global symbol defined in a discarded section.  */
       if (h->indx == -3)
@@ -10563,6 +10667,18 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 
       /* If this symbol is defined in a section which we are
         discarding, we don't need to keep it.  */
+      if (isym->st_shndx != SHN_UNDEF
+         && isym->st_shndx < SHN_LORESERVE
+         && isec->output_section == NULL
+         && flinfo->info->non_contiguous_regions
+         && flinfo->info->non_contiguous_regions_warnings)
+       {
+         _bfd_error_handler (_("warning: --enable-non-contiguous-regions "
+                               "discards section `%s' from '%s'\n"),
+                             isec->name, isec->owner->filename);
+         continue;
+       }
+
       if (isym->st_shndx != SHN_UNDEF
          && isym->st_shndx < SHN_LORESERVE
          && bfd_section_removed_from_list (output_bfd,
@@ -11562,8 +11678,8 @@ elf_fixup_link_order (bfd *abfd, asection *o)
   struct bfd_link_order *p;
   bfd *sub;
   struct bfd_link_order **sections;
-  asection *s, *other_sec, *linkorder_sec;
-  bfd_vma offset;
+  asection *other_sec, *linkorder_sec;
+  bfd_vma offset;  /* Octets.  */
 
   other_sec = NULL;
   linkorder_sec = NULL;
@@ -11573,7 +11689,7 @@ elf_fixup_link_order (bfd *abfd, asection *o)
     {
       if (p->type == bfd_indirect_link_order)
        {
-         s = p->u.indirect.section;
+         asection *s = p->u.indirect.section;
          sub = s->owner;
          if ((s->flags & SEC_LINKER_CREATED) == 0
              && bfd_get_flavour (sub) == bfd_target_elf_flavour
@@ -11628,11 +11744,12 @@ elf_fixup_link_order (bfd *abfd, asection *o)
   for (n = 0; n < seen_linkorder; n++)
     {
       bfd_vma mask;
-      s = sections[n]->u.indirect.section;
-      mask = ~(bfd_vma) 0 << s->alignment_power;
+      asection *s = sections[n]->u.indirect.section;
+      unsigned int opb = bfd_octets_per_byte (abfd, s);
+
+      mask = ~(bfd_vma) 0 << s->alignment_power * opb;
       offset = (offset + ~mask) & mask;
-      s->output_offset = offset / bfd_octets_per_byte (abfd, s);
-      sections[n]->offset = offset;
+      sections[n]->offset = s->output_offset = offset / opb;
       offset += sections[n]->size;
     }
 
@@ -11745,7 +11862,7 @@ elf_output_implib (bfd *abfd, struct bfd_link_info *info)
 
   ret = TRUE;
 
-free_sym_buf:
+ free_sym_buf:
   free (sympp);
   return ret;
 }
@@ -12243,7 +12360,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
   if (htab->tls_sec)
     {
-      bfd_vma base, end = 0;
+      bfd_vma base, end = 0;  /* Both bytes.  */
       asection *sec;
 
       for (sec = htab->tls_sec;
@@ -12251,6 +12368,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
           sec = sec->next)
        {
          bfd_size_type size = sec->size;
+         unsigned int opb = bfd_octets_per_byte (abfd, sec);
 
          if (size == 0
              && (sec->flags & SEC_HAS_CONTENTS) == 0)
@@ -12258,9 +12376,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
              struct bfd_link_order *ord = sec->map_tail.link_order;
 
              if (ord != NULL)
-               size = ord->offset + ord->size;
+               size = ord->offset * opb + ord->size;
            }
-         end = sec->vma + size;
+         end = sec->vma + size / opb;
        }
       base = htab->tls_sec->vma;
       /* Only align end of TLS section if static TLS doesn't have special
@@ -12773,6 +12891,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
              if (bed->dtrel_excludes_plt && htab->srelplt != NULL)
                {
+                 unsigned int opb = bfd_octets_per_byte (abfd, o);
+
                  /* Don't count procedure linkage table relocs in the
                     overall reloc count.  */
                  sh_size -= htab->srelplt->size;
@@ -12792,7 +12912,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                  /* If .rela.plt is the first .rela section, exclude
                     it from DT_RELA.  */
                  else if (sh_addr == (htab->srelplt->output_section->vma
-                                      + htab->srelplt->output_offset))
+                                      + htab->srelplt->output_offset) * opb)
                    sh_addr += htab->srelplt->size;
                }
 
@@ -14247,7 +14367,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
     {
       asection *i;
       int eh_changed = 0;
-      unsigned int eh_alignment;
+      unsigned int eh_alignment;  /* Octets.  */
 
       for (i = o->map_head.s; i != NULL; i = i->map_head.s)
        {
@@ -14274,7 +14394,8 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
          fini_reloc_cookie_for_section (&cookie, i);
        }
 
-      eh_alignment = 1 << o->alignment_power;
+      eh_alignment = ((1 << o->alignment_power)
+                     * bfd_octets_per_byte (output_bfd, o));
       /* Skip over zero terminator, and prevent empty sections from
         adding alignment padding at the end.  */
       for (i = o->map_tail.s; i != NULL; i = i->map_tail.s)
This page took 0.030421 seconds and 4 git commands to generate.