Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / elflink.c
index c04712a10f6a6b188882380709bc04f40a5a7fd2..f87927f0bd8f7b71d41ff23c517d49d8895728ad 100644 (file)
@@ -2643,8 +2643,7 @@ _bfd_elf_link_read_relocs (bfd *abfd,
   if (keep_memory)
     esdo->relocs = internal_relocs;
 
-  if (alloc1 != NULL)
-    free (alloc1);
+  free (alloc1);
 
   /* Don't free alloc2, since if it was allocated we are passing it
      back (under the name of internal_relocs).  */
@@ -2652,8 +2651,7 @@ _bfd_elf_link_read_relocs (bfd *abfd,
   return internal_relocs;
 
  error_return:
-  if (alloc1 != NULL)
-    free (alloc1);
+  free (alloc1);
   if (alloc2 != NULL)
     {
       if (keep_memory)
@@ -3323,8 +3321,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 +3499,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.  */
 
@@ -4218,10 +4314,14 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
        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;
          }
 
@@ -5197,17 +5297,10 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
        }
     }
 
-  if (extversym != NULL)
-    {
-      free (extversym);
-      extversym = NULL;
-    }
-
-  if (isymbuf != NULL)
-    {
-      free (isymbuf);
-      isymbuf = NULL;
-    }
+  free (extversym);
+  extversym = NULL;
+  free (isymbuf);
+  isymbuf = NULL;
 
   if ((elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0)
     {
@@ -5287,8 +5380,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
       free (old_tab);
       objalloc_free_block ((struct objalloc *) htab->root.table.memory,
                           alloc_mark);
-      if (nondeflt_vers != NULL)
-       free (nondeflt_vers);
+      free (nondeflt_vers);
       return TRUE;
     }
 
@@ -5571,17 +5663,12 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   return TRUE;
 
  error_free_vers:
-  if (old_tab != NULL)
-    free (old_tab);
-  if (old_strtab != NULL)
-    free (old_strtab);
-  if (nondeflt_vers != NULL)
-    free (nondeflt_vers);
-  if (extversym != NULL)
-    free (extversym);
+  free (old_tab);
+  free (old_strtab);
+  free (nondeflt_vers);
+  free (extversym);
  error_free_sym:
-  if (isymbuf != NULL)
-    free (isymbuf);
+  free (isymbuf);
  error_return:
   return FALSE;
 }
@@ -5789,12 +5876,10 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
   while (loop);
 
   free (included);
-
   return TRUE;
 
  error_return:
-  if (included != NULL)
-    free (included);
+  free (included);
   return FALSE;
 }
 
@@ -5865,9 +5950,7 @@ elf_collect_hash_codes (struct elf_link_hash_entry *h, void *data)
      later.  */
   h->u.elf_hash_value = ha;
 
-  if (alc != NULL)
-    free (alc);
-
+  free (alc);
   return TRUE;
 }
 
@@ -5941,9 +6024,7 @@ elf_collect_gnu_hash_codes (struct elf_link_hash_entry *h, void *data)
   if (s->min_dynindx < 0 || s->min_dynindx > h->dynindx)
     s->min_dynindx = h->dynindx;
 
-  if (alc != NULL)
-    free (alc);
-
+  free (alc);
   return TRUE;
 }
 
@@ -6521,7 +6602,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
            {
              size_t indx;
 
-             name = lbasename (output_bfd->filename);
+             name = lbasename (bfd_get_filename (output_bfd));
              def.vd_hash = bfd_elf_hash (name);
              indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
                                          name, FALSE);
@@ -6748,7 +6829,8 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
              indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr,
                                          elf_dt_name (vn->vn_bfd) != NULL
                                          ? elf_dt_name (vn->vn_bfd)
-                                         : lbasename (vn->vn_bfd->filename),
+                                         : lbasename (bfd_get_filename
+                                                      (vn->vn_bfd)),
                                          FALSE);
              if (indx == (size_t) -1)
                return FALSE;
@@ -7870,8 +7952,7 @@ bfd_elf_get_bfd_needed_list (bfd *abfd,
   return TRUE;
 
  error_return:
-  if (dynbuf != NULL)
-    free (dynbuf);
+  free (dynbuf);
   return FALSE;
 }
 
@@ -8210,14 +8291,10 @@ bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
   result = TRUE;
 
  done:
-  if (symtable1)
-    free (symtable1);
-  if (symtable2)
-    free (symtable2);
-  if (isymbuf1)
-    free (isymbuf1);
-  if (isymbuf2)
-    free (isymbuf2);
+  free (symtable1);
+  free (symtable2);
+  free (isymbuf1);
+  free (isymbuf2);
 
   return result;
 }
@@ -9882,11 +9959,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 +10642,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, bfd_get_filename (isec->owner));
+         continue;
+       }
+
       if (isym->st_shndx != SHN_UNDEF
          && isym->st_shndx < SHN_LORESERVE
          && bfd_section_removed_from_list (output_bfd,
@@ -10610,7 +10701,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
          osym.st_shndx = SHN_ABS;
          if (!elf_link_output_symstrtab (flinfo,
                                          (input_bfd->lto_output ? NULL
-                                          : input_bfd->filename),
+                                          : bfd_get_filename (input_bfd)),
                                          &osym, bfd_abs_section_ptr,
                                          NULL))
            return FALSE;
@@ -10912,7 +11003,7 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 #ifdef DEBUG
                  printf ("Encountered a complex symbol!");
                  printf (" (input_bfd %s, section %s, reloc %ld\n",
-                         input_bfd->filename, o->name,
+                         bfd_get_filename (input_bfd), o->name,
                          (long) (rel - internal_relocs));
                  printf (" symbol: idx  %8.8lx, name %s\n",
                          r_symndx, sym_name);
@@ -11562,8 +11653,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 +11664,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 +11719,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;
     }
 
@@ -11757,32 +11849,21 @@ elf_final_link_free (bfd *obfd, struct elf_final_link_info *flinfo)
 
   if (flinfo->symstrtab != NULL)
     _bfd_elf_strtab_free (flinfo->symstrtab);
-  if (flinfo->contents != NULL)
-    free (flinfo->contents);
-  if (flinfo->external_relocs != NULL)
-    free (flinfo->external_relocs);
-  if (flinfo->internal_relocs != NULL)
-    free (flinfo->internal_relocs);
-  if (flinfo->external_syms != NULL)
-    free (flinfo->external_syms);
-  if (flinfo->locsym_shndx != NULL)
-    free (flinfo->locsym_shndx);
-  if (flinfo->internal_syms != NULL)
-    free (flinfo->internal_syms);
-  if (flinfo->indices != NULL)
-    free (flinfo->indices);
-  if (flinfo->sections != NULL)
-    free (flinfo->sections);
-  if (flinfo->symshndxbuf != NULL
-      && flinfo->symshndxbuf != (Elf_External_Sym_Shndx *) -1)
+  free (flinfo->contents);
+  free (flinfo->external_relocs);
+  free (flinfo->internal_relocs);
+  free (flinfo->external_syms);
+  free (flinfo->locsym_shndx);
+  free (flinfo->internal_syms);
+  free (flinfo->indices);
+  free (flinfo->sections);
+  if (flinfo->symshndxbuf != (Elf_External_Sym_Shndx *) -1)
     free (flinfo->symshndxbuf);
   for (o = obfd->sections; o != NULL; o = o->next)
     {
       struct bfd_elf_section_data *esdo = elf_section_data (o);
-      if ((o->flags & SEC_RELOC) != 0 && esdo->rel.hashes != NULL)
-       free (esdo->rel.hashes);
-      if ((o->flags & SEC_RELOC) != 0 && esdo->rela.hashes != NULL)
-       free (esdo->rela.hashes);
+      free (esdo->rel.hashes);
+      free (esdo->rela.hashes);
     }
 }
 
@@ -12243,7 +12324,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 +12332,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 +12340,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
@@ -12369,8 +12451,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   if (!info->reduce_memory_overheads)
     {
       for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
-       if (bfd_get_flavour (sub) == bfd_target_elf_flavour
-           && elf_tdata (sub)->symbuf)
+       if (bfd_get_flavour (sub) == bfd_target_elf_flavour)
          {
            free (elf_tdata (sub)->symbuf);
            elf_tdata (sub)->symbuf = NULL;
@@ -12773,6 +12854,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 +12875,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;
                }
 
@@ -12813,8 +12896,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
        goto error_return;
 
       /* Check for DT_TEXTREL (late, in case the backend removes it).  */
-      if (((info->warn_shared_textrel && bfd_link_pic (info))
-          || info->error_textrel)
+      if (bfd_link_textrel_check (info)
          && (o = bfd_get_linker_section (dynobj, ".dynamic")) != NULL)
        {
          bfd_byte *dyncon, *dynconend;
@@ -12829,12 +12911,15 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 
              if (dyn.d_tag == DT_TEXTREL)
                {
-                 if (info->error_textrel)
+                 if (info->textrel_check == textrel_check_error)
                    info->callbacks->einfo
                      (_("%P%X: read-only segment has dynamic relocations\n"));
+                 else if (bfd_link_dll (info))
+                   info->callbacks->einfo
+                     (_("%P: warning: creating DT_TEXTREL in a shared object\n"));
                  else
                    info->callbacks->einfo
-                     (_("%P: warning: creating a DT_TEXTREL in a shared object\n"));
+                     (_("%P: warning: creating DT_TEXTREL in a PIE\n"));
                  break;
                }
            }
@@ -12976,8 +13061,7 @@ fini_reloc_cookie (struct elf_reloc_cookie *cookie, bfd *abfd)
   Elf_Internal_Shdr *symtab_hdr;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  if (cookie->locsyms != NULL
-      && symtab_hdr->contents != (unsigned char *) cookie->locsyms)
+  if (symtab_hdr->contents != (unsigned char *) cookie->locsyms)
     free (cookie->locsyms);
 }
 
@@ -13014,7 +13098,7 @@ static void
 fini_reloc_cookie_rels (struct elf_reloc_cookie *cookie,
                        asection *sec)
 {
-  if (cookie->rels && elf_section_data (sec)->relocs != cookie->rels)
+  if (elf_section_data (sec)->relocs != cookie->rels)
     free (cookie->rels);
 }
 
@@ -14247,7 +14331,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 +14358,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.032412 seconds and 4 git commands to generate.