bfd/
[deliverable/binutils-gdb.git] / bfd / elf.c
index 71e16f7518d0773ea00d867084dc6bf05d8eb79e..13f690465ee12b9b7604536ff8a0e366fe5b5f88 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1,7 +1,8 @@
 /* ELF executable support for BFD.
 
    Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -258,7 +259,7 @@ bfd_elf_mkcorefile (bfd *abfd)
   return bfd_elf_make_generic_object (abfd);
 }
 
-char *
+static char *
 bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
 {
   Elf_Internal_Shdr **i_shdrp;
@@ -330,7 +331,7 @@ bfd_elf_string_from_elf_section (bfd *abfd,
         (shindex == shstrndx && strindex == hdr->sh_name
          ? ".shstrtab"
          : bfd_elf_string_from_elf_section (abfd, shstrndx, hdr->sh_name)));
-      return "";
+      return NULL;
     }
 
   return ((char *) hdr->contents) + strindex;
@@ -358,6 +359,7 @@ bfd_elf_get_elf_syms (bfd *ibfd,
   const bfd_byte *esym;
   Elf_External_Sym_Shndx *alloc_extshndx;
   Elf_External_Sym_Shndx *shndx;
+  Elf_Internal_Sym *alloc_intsym;
   Elf_Internal_Sym *isym;
   Elf_Internal_Sym *isymend;
   const struct elf_backend_data *bed;
@@ -379,6 +381,7 @@ bfd_elf_get_elf_syms (bfd *ibfd,
   /* Read the symbols.  */
   alloc_ext = NULL;
   alloc_extshndx = NULL;
+  alloc_intsym = NULL;
   bed = get_elf_backend_data (ibfd);
   extsym_size = bed->s->sizeof_sym;
   amt = symcount * extsym_size;
@@ -419,7 +422,8 @@ bfd_elf_get_elf_syms (bfd *ibfd,
 
   if (intsym_buf == NULL)
     {
-      intsym_buf = bfd_malloc2 (symcount, sizeof (Elf_Internal_Sym));
+      alloc_intsym = bfd_malloc2 (symcount, sizeof (Elf_Internal_Sym));
+      intsym_buf = alloc_intsym;
       if (intsym_buf == NULL)
        goto out;
     }
@@ -435,6 +439,8 @@ bfd_elf_get_elf_syms (bfd *ibfd,
        (*_bfd_error_handler) (_("%B symbol number %lu references "
                                 "nonexistent SHT_SYMTAB_SHNDX section"),
                               ibfd, (unsigned long) symoffset);
+       if (alloc_intsym != NULL)
+         free (alloc_intsym);
        intsym_buf = NULL;
        goto out;
       }
@@ -965,25 +971,8 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
       phdr = elf_tdata (abfd)->phdr;
       for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
        {
-         /* This section is part of this segment if its file
-            offset plus size lies within the segment's memory
-            span and, if the section is loaded, the extent of the
-            loaded data lies within the extent of the segment.
-
-            Note - we used to check the p_paddr field as well, and
-            refuse to set the LMA if it was 0.  This is wrong
-            though, as a perfectly valid initialised segment can
-            have a p_paddr of zero.  Some architectures, eg ARM,
-            place special significance on the address 0 and
-            executables need to be able to have a segment which
-            covers this address.  */
          if (phdr->p_type == PT_LOAD
-             && (bfd_vma) hdr->sh_offset >= phdr->p_offset
-             && (hdr->sh_offset + hdr->sh_size
-                 <= phdr->p_offset + phdr->p_memsz)
-             && ((flags & SEC_LOAD) == 0
-                 || (hdr->sh_offset + hdr->sh_size
-                     <= phdr->p_offset + phdr->p_filesz)))
+             && ELF_IS_SECTION_IN_SEGMENT (hdr, phdr))
            {
              if ((flags & SEC_LOAD) == 0)
                newsect->lma = (phdr->p_paddr
@@ -1014,45 +1003,6 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
   return TRUE;
 }
 
-/*
-INTERNAL_FUNCTION
-       bfd_elf_find_section
-
-SYNOPSIS
-       struct elf_internal_shdr *bfd_elf_find_section (bfd *abfd, char *name);
-
-DESCRIPTION
-       Helper functions for GDB to locate the string tables.
-       Since BFD hides string tables from callers, GDB needs to use an
-       internal hook to find them.  Sun's .stabstr, in particular,
-       isn't even pointed to by the .stab section, so ordinary
-       mechanisms wouldn't work to find it, even if we had some.
-*/
-
-struct elf_internal_shdr *
-bfd_elf_find_section (bfd *abfd, char *name)
-{
-  Elf_Internal_Shdr **i_shdrp;
-  char *shstrtab;
-  unsigned int max;
-  unsigned int i;
-
-  i_shdrp = elf_elfsections (abfd);
-  if (i_shdrp != NULL)
-    {
-      shstrtab = bfd_elf_get_str_section (abfd,
-                                         elf_elfheader (abfd)->e_shstrndx);
-      if (shstrtab != NULL)
-       {
-         max = elf_numsections (abfd);
-         for (i = 1; i < max; i++)
-           if (!strcmp (&shstrtab[i_shdrp[i]->sh_name], name))
-             return i_shdrp[i];
-       }
-    }
-  return 0;
-}
-
 const char *const bfd_elf_section_type_names[] = {
   "SHT_NULL", "SHT_PROGBITS", "SHT_SYMTAB", "SHT_STRTAB",
   "SHT_RELA", "SHT_HASH", "SHT_DYNAMIC", "SHT_NOTE",
@@ -1393,7 +1343,7 @@ bfd_elf_print_symbol (bfd *abfd,
     case bfd_print_symbol_more:
       fprintf (file, "elf ");
       bfd_fprintf_vma (abfd, file, symbol->value);
-      fprintf (file, " %lx", (long) symbol->flags);
+      fprintf (file, " %lx", (unsigned long) symbol->flags);
       break;
     case bfd_print_symbol_all:
       {
@@ -1603,6 +1553,8 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
 
       if (hdr->sh_entsize != bed->s->sizeof_sym)
        return FALSE;
+      if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size)
+       return FALSE;
       BFD_ASSERT (elf_onesymtab (abfd) == 0);
       elf_onesymtab (abfd) = shindex;
       elf_tdata (abfd)->symtab_hdr = *hdr;
@@ -1759,8 +1711,11 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
           reject them, but, unfortunately, some people need to use
           them.  We scan through the section headers; if we find only
           one suitable symbol table, we clobber the sh_link to point
-          to it.  I hope this doesn't break anything.  */
-       if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_SYMTAB
+          to it.  I hope this doesn't break anything.
+
+          Don't do it on executable nor shared library.  */
+       if ((abfd->flags & (DYNAMIC | EXEC_P)) == 0
+           && elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_SYMTAB
            && elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_DYNSYM)
          {
            unsigned int scan;
@@ -1795,8 +1750,10 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
           represent such a section, so at least for now, we don't
           try.  We just present it as a normal section.  We also
           can't use it as a reloc section if it points to the null
-          section, an invalid section, or another reloc section.  */
+          section, an invalid section, another reloc section, or its
+          sh_link points to the null section.  */
        if (hdr->sh_link != elf_onesymtab (abfd)
+           || hdr->sh_link == SHN_UNDEF
            || hdr->sh_info == SHN_UNDEF
            || hdr->sh_info >= num_sec
            || elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_REL
@@ -1858,14 +1815,8 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
       return TRUE;
 
     case SHT_GROUP:
-      /* We need a BFD section for objcopy and relocatable linking,
-        and it's handy to have the signature available as the section
-        name.  */
       if (! IS_VALID_GROUP_SECTION_HEADER (hdr))
        return FALSE;
-      name = group_signature (abfd, hdr);
-      if (name == NULL)
-       return FALSE;
       if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
        return FALSE;
       if (hdr->contents != NULL)
@@ -1958,28 +1909,24 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
   return TRUE;
 }
 
-/* Return the section for the local symbol specified by ABFD, R_SYMNDX.
-   Return SEC for sections that have no elf section, and NULL on error.  */
+/* Return the local symbol specified by ABFD, R_SYMNDX.  */
 
-asection *
-bfd_section_from_r_symndx (bfd *abfd,
-                          struct sym_sec_cache *cache,
-                          asection *sec,
-                          unsigned long r_symndx)
+Elf_Internal_Sym *
+bfd_sym_from_r_symndx (struct sym_cache *cache,
+                      bfd *abfd,
+                      unsigned long r_symndx)
 {
   unsigned int ent = r_symndx % LOCAL_SYM_CACHE_SIZE;
-  asection *s;
 
   if (cache->abfd != abfd || cache->indx[ent] != r_symndx)
     {
       Elf_Internal_Shdr *symtab_hdr;
       unsigned char esym[sizeof (Elf64_External_Sym)];
       Elf_External_Sym_Shndx eshndx;
-      Elf_Internal_Sym isym;
 
       symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
       if (bfd_elf_get_elf_syms (abfd, symtab_hdr, 1, r_symndx,
-                               &isym, esym, &eshndx) == NULL)
+                               &cache->sym[ent], esym, &eshndx) == NULL)
        return NULL;
 
       if (cache->abfd != abfd)
@@ -1988,14 +1935,9 @@ bfd_section_from_r_symndx (bfd *abfd,
          cache->abfd = abfd;
        }
       cache->indx[ent] = r_symndx;
-      cache->shndx[ent] = isym.st_shndx;
     }
 
-  s = bfd_section_from_elf_index (abfd, cache->shndx[ent]);
-  if (s != NULL)
-    return s;
-
-  return sec;
+  return &cache->sym[ent];
 }
 
 /* Given an ELF section number, retrieve the corresponding BFD
@@ -2480,6 +2422,18 @@ _bfd_elf_init_reloc_shdr (bfd *abfd,
   return TRUE;
 }
 
+/* Return the default section type based on the passed in section flags.  */
+
+int
+bfd_elf_get_default_section_type (flagword flags)
+{
+  if ((flags & SEC_ALLOC) != 0
+      && ((flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0
+         || (flags & SEC_NEVER_LOAD) != 0))
+    return SHT_NOBITS;
+  return SHT_PROGBITS;
+}
+
 /* Set up an ELF internal section header for a section.  */
 
 static void
@@ -2529,12 +2483,8 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg)
      asect->flags.  */
   if ((asect->flags & SEC_GROUP) != 0)
     sh_type = SHT_GROUP;
-  else if ((asect->flags & SEC_ALLOC) != 0
-          && (((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
-              || (asect->flags & SEC_NEVER_LOAD) != 0))
-    sh_type = SHT_NOBITS;
   else
-    sh_type = SHT_PROGBITS;
+    sh_type = bfd_elf_get_default_section_type (asect->flags);
 
   if (this_hdr->sh_type == SHT_NULL)
     this_hdr->sh_type = sh_type;
@@ -2682,13 +2632,15 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg)
     *failedptr = TRUE;
 }
 
-/* Fill in the contents of a SHT_GROUP section.  */
+/* Fill in the contents of a SHT_GROUP section.  Called from
+   _bfd_elf_compute_section_file_positions for gas, objcopy, and
+   when ELF targets use the generic linker, ld.  Called for ld -r
+   from bfd_elf_final_link.  */
 
 void
 bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg)
 {
   bfd_boolean *failedptr = failedptrarg;
-  unsigned long symindx;
   asection *elt, *first;
   unsigned char *loc;
   bfd_boolean gas;
@@ -2699,20 +2651,49 @@ bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg)
       || *failedptr)
     return;
 
-  symindx = 0;
-  if (elf_group_id (sec) != NULL)
-    symindx = elf_group_id (sec)->udata.i;
+  if (elf_section_data (sec)->this_hdr.sh_info == 0)
+    {
+      unsigned long symindx = 0;
+
+      /* elf_group_id will have been set up by objcopy and the
+        generic linker.  */
+      if (elf_group_id (sec) != NULL)
+       symindx = elf_group_id (sec)->udata.i;
 
-  if (symindx == 0)
+      if (symindx == 0)
+       {
+         /* If called from the assembler, swap_out_syms will have set up
+            elf_section_syms.  */
+         BFD_ASSERT (elf_section_syms (abfd) != NULL);
+         symindx = elf_section_syms (abfd)[sec->index]->udata.i;
+       }
+      elf_section_data (sec)->this_hdr.sh_info = symindx;
+    }
+  else if (elf_section_data (sec)->this_hdr.sh_info == (unsigned int) -2)
     {
-      /* If called from the assembler, swap_out_syms will have set up
-        elf_section_syms;  If called for "ld -r", use target_index.  */
-      if (elf_section_syms (abfd) != NULL)
-       symindx = elf_section_syms (abfd)[sec->index]->udata.i;
-      else
-       symindx = sec->target_index;
+      /* The ELF backend linker sets sh_info to -2 when the group
+        signature symbol is global, and thus the index can't be
+        set until all local symbols are output.  */
+      asection *igroup = elf_sec_group (elf_next_in_group (sec));
+      struct bfd_elf_section_data *sec_data = elf_section_data (igroup);
+      unsigned long symndx = sec_data->this_hdr.sh_info;
+      unsigned long extsymoff = 0;
+      struct elf_link_hash_entry *h;
+
+      if (!elf_bad_symtab (igroup->owner))
+       {
+         Elf_Internal_Shdr *symtab_hdr;
+
+         symtab_hdr = &elf_tdata (igroup->owner)->symtab_hdr;
+         extsymoff = symtab_hdr->sh_info;
+       }
+      h = elf_sym_hashes (igroup->owner)[symndx - extsymoff];
+      while (h->root.type == bfd_link_hash_indirect
+            || h->root.type == bfd_link_hash_warning)
+       h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+      elf_section_data (sec)->this_hdr.sh_info = h->indx;
     }
-  elf_section_data (sec)->this_hdr.sh_info = symindx;
 
   /* The contents won't be allocated for "ld -r" or objcopy.  */
   gas = TRUE;
@@ -2746,14 +2727,17 @@ bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg)
       asection *s;
       unsigned int idx;
 
-      loc -= 4;
       s = elt;
-      if (!gas)
-       s = s->output_section;
-      idx = 0;
-      if (s != NULL)
-       idx = elf_section_data (s)->this_idx;
-      H_PUT_32 (abfd, idx, loc);
+      if (! elf_discarded_section (s))
+       {
+         loc -= 4;
+         if (!gas)
+           s = s->output_section;
+         idx = 0;
+         if (s != NULL)
+           idx = elf_section_data (s)->this_idx;
+         H_PUT_32 (abfd, idx, loc);
+       }
       elt = elf_next_in_group (elt);
       if (elt == first)
        break;
@@ -2777,6 +2761,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
   unsigned int section_number, secn;
   Elf_Internal_Shdr **i_shdrp;
   struct bfd_elf_section_data *d;
+  bfd_boolean need_symtab;
 
   section_number = 1;
 
@@ -2832,7 +2817,11 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
   _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->shstrtab_hdr.sh_name);
   elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section;
 
-  if (bfd_get_symcount (abfd) > 0)
+  need_symtab = (bfd_get_symcount (abfd) > 0
+               || (link_info == NULL
+                   && ((abfd->flags & (EXEC_P | DYNAMIC | HAS_RELOC))
+                       == HAS_RELOC)));
+  if (need_symtab)
     {
       t->symtab_section = section_number++;
       _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name);
@@ -2871,7 +2860,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
   elf_elfsections (abfd) = i_shdrp;
 
   i_shdrp[t->shstrtab_section] = &t->shstrtab_hdr;
-  if (bfd_get_symcount (abfd) > 0)
+  if (need_symtab)
     {
       i_shdrp[t->symtab_section] = &t->symtab_hdr;
       if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF))
@@ -3086,7 +3075,7 @@ sym_is_global (bfd *abfd, asymbol *sym)
   if (bed->elf_backend_sym_is_global)
     return (*bed->elf_backend_sym_is_global) (abfd, sym);
 
-  return ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
+  return ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0
          || bfd_is_und_section (bfd_get_section (sym))
          || bfd_is_com_section (bfd_get_section (sym)));
 }
@@ -3264,6 +3253,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
   bfd_boolean failed;
   struct bfd_strtab_hash *strtab = NULL;
   Elf_Internal_Shdr *shstrtab_hdr;
+  bfd_boolean need_symtab;
 
   if (abfd->output_has_begun)
     return TRUE;
@@ -3288,7 +3278,11 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
     return FALSE;
 
   /* The backend linker builds symbol table information itself.  */
-  if (link_info == NULL && bfd_get_symcount (abfd) > 0)
+  need_symtab = (link_info == NULL
+                && (bfd_get_symcount (abfd) > 0
+                    || ((abfd->flags & (EXEC_P | DYNAMIC | HAS_RELOC))
+                        == HAS_RELOC)));
+  if (need_symtab)
     {
       /* Non-zero if doing a relocatable link.  */
       int relocatable_p = ! (abfd->flags & (EXEC_P | DYNAMIC));
@@ -3319,7 +3313,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
   if (!assign_file_positions_except_relocs (abfd, link_info))
     return FALSE;
 
-  if (link_info == NULL && bfd_get_symcount (abfd) > 0)
+  if (need_symtab)
     {
       file_ptr off;
       Elf_Internal_Shdr *hdr;
@@ -3381,7 +3375,7 @@ get_program_header_size (bfd *abfd, struct bfd_link_info *info)
       ++segs;
     }
 
-  if (info->relro)
+  if (info != NULL && info->relro)
     {
       /* We need a PT_GNU_RELRO segment.  */
       ++segs;
@@ -3763,8 +3757,13 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
            }
 
          /* Allow interested parties a chance to override our decision.  */
-         if (last_hdr && info->callbacks->override_segment_assignment)
-           new_segment = info->callbacks->override_segment_assignment (info, abfd, hdr, last_hdr, new_segment);
+         if (last_hdr != NULL
+             && info != NULL
+             && info->callbacks->override_segment_assignment != NULL)
+           new_segment
+             = info->callbacks->override_segment_assignment (info, abfd, hdr,
+                                                             last_hdr,
+                                                             new_segment);
 
          if (! new_segment)
            {
@@ -3939,7 +3938,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
          pm = &m->next;
        }
 
-      if (info->relro)
+      if (info != NULL && info->relro)
        {
          for (m = mfirst; m != NULL; m = m->next)
            {
@@ -4121,14 +4120,19 @@ assign_file_positions_for_load_sections (bfd *abfd,
   bfd_size_type maxpagesize;
   unsigned int alloc;
   unsigned int i, j;
+  bfd_vma header_pad = 0;
 
   if (link_info == NULL
-      && !elf_modify_segment_map (abfd, link_info, FALSE))
+      && !_bfd_elf_map_sections_to_segments (abfd, link_info))
     return FALSE;
 
   alloc = 0;
   for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
-    ++alloc;
+    {
+      ++alloc;
+      if (m->header_size)
+       header_pad = m->header_size;
+    }
 
   elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr;
   elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr;
@@ -4146,7 +4150,21 @@ assign_file_positions_for_load_sections (bfd *abfd,
       return TRUE;
     }
 
-  phdrs = bfd_alloc2 (abfd, alloc, sizeof (Elf_Internal_Phdr));
+  /* We're writing the size in elf_tdata (abfd)->program_header_size,
+     see assign_file_positions_except_relocs, so make sure we have
+     that amount allocated, with trailing space cleared.
+     The variable alloc contains the computed need, while elf_tdata
+     (abfd)->program_header_size contains the size used for the
+     layout.
+     See ld/emultempl/elf-generic.em:gld${EMULATION_NAME}_map_segments
+     where the layout is forced to according to a larger size in the
+     last iterations for the testcase ld-elf/header.  */
+  BFD_ASSERT (elf_tdata (abfd)->program_header_size % bed->s->sizeof_phdr
+             == 0);
+  phdrs = bfd_zalloc2 (abfd,
+                      (elf_tdata (abfd)->program_header_size
+                       / bed->s->sizeof_phdr),
+                      sizeof (Elf_Internal_Phdr));
   elf_tdata (abfd)->phdr = phdrs;
   if (phdrs == NULL)
     return FALSE;
@@ -4157,6 +4175,11 @@ assign_file_positions_for_load_sections (bfd *abfd,
 
   off = bed->s->sizeof_ehdr;
   off += alloc * bed->s->sizeof_phdr;
+  if (header_pad < (bfd_vma) off)
+    header_pad = 0;
+  else
+    header_pad -= off;
+  off += header_pad;
 
   for (m = elf_tdata (abfd)->segment_map, p = phdrs, j = 0;
        m != NULL;
@@ -4253,21 +4276,14 @@ assign_file_positions_for_load_sections (bfd *abfd,
              elf_section_type (m->sections[i]) = SHT_NOBITS;
 
          /* Find out whether this segment contains any loadable
-            sections.  If the first section isn't loadable, the same
-            holds for any other sections.  */
-         i = 0;
-         while (elf_section_type (m->sections[i]) == SHT_NOBITS)
-           {
-             /* If a segment starts with .tbss, we need to look
-                at the next section to decide whether the segment
-                has any loadable sections.  */
-             if ((elf_section_flags (m->sections[i]) & SHF_TLS) == 0
-                 || ++i >= m->count)
-               {
-                 no_contents = TRUE;
-                 break;
-               }
-           }
+            sections.  */
+         no_contents = TRUE;
+         for (i = 0; i < m->count; i++)
+           if (elf_section_type (m->sections[i]) != SHT_NOBITS)
+             {
+               no_contents = FALSE;
+               break;
+             }
 
          off_adjust = vma_page_aligned_bias (m->sections[0]->vma, off, align);
          off += off_adjust;
@@ -4351,6 +4367,11 @@ assign_file_positions_for_load_sections (bfd *abfd,
 
          p->p_filesz += alloc * bed->s->sizeof_phdr;
          p->p_memsz += alloc * bed->s->sizeof_phdr;
+         if (m->count)
+           {
+             p->p_filesz += header_pad;
+             p->p_memsz += header_pad;
+           }
        }
 
       if (p->p_type == PT_LOAD
@@ -4603,7 +4624,59 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
        m != NULL;
        m = m->next, p++)
     {
-      if (m->count != 0)
+      if (p->p_type == PT_GNU_RELRO)
+       {
+         const Elf_Internal_Phdr *lp;
+
+         BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs);
+
+         if (link_info != NULL)
+           {
+             /* During linking the range of the RELRO segment is passed
+                in link_info.  */
+             for (lp = phdrs; lp < phdrs + count; ++lp)
+               {
+                 if (lp->p_type == PT_LOAD
+                     && lp->p_vaddr >= link_info->relro_start
+                     && lp->p_vaddr < link_info->relro_end
+                     && lp->p_vaddr + lp->p_filesz >= link_info->relro_end)
+                   break;
+               }
+           }
+         else
+           {
+             /* Otherwise we are copying an executable or shared
+                library, but we need to use the same linker logic.  */
+             for (lp = phdrs; lp < phdrs + count; ++lp)
+               {
+                 if (lp->p_type == PT_LOAD
+                     && lp->p_paddr == p->p_paddr)
+                   break;
+               }
+           }
+
+         if (lp < phdrs + count)
+           {
+             p->p_vaddr = lp->p_vaddr;
+             p->p_paddr = lp->p_paddr;
+             p->p_offset = lp->p_offset;
+             if (link_info != NULL)
+               p->p_filesz = link_info->relro_end - lp->p_vaddr;
+             else if (m->p_size_valid)
+               p->p_filesz = m->p_size;
+             else
+               abort ();
+             p->p_memsz = p->p_filesz;
+             p->p_align = 1;
+             p->p_flags = (lp->p_flags & ~PF_W);
+           }
+         else
+           {
+             memset (p, 0, sizeof *p);
+             p->p_type = PT_NULL;
+           }
+       }
+      else if (m->count != 0)
        {
          if (p->p_type != PT_LOAD
              && (p->p_type != PT_NOTE
@@ -4619,87 +4692,20 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
              p->p_filesz = sect->filepos - m->sections[0]->filepos;
              if (hdr->sh_type != SHT_NOBITS)
                p->p_filesz += hdr->sh_size;
-
-             if (p->p_type == PT_GNU_RELRO)
-               {
-                 /* When we get here, we are copying executable
-                    or shared library. But we need to use the same
-                    linker logic.  */
-                 Elf_Internal_Phdr *lp;
-
-                 for (lp = phdrs; lp < phdrs + count; ++lp)
-                   {
-                     if (lp->p_type == PT_LOAD
-                         && lp->p_paddr == p->p_paddr)
-                       break;
-                   }
-         
-                 if (lp < phdrs + count)
-                   {
-                     /* We should use p_size if it is valid since it
-                        may contain the first few bytes of the next
-                        SEC_ALLOC section.  */
-                     if (m->p_size_valid)
-                       p->p_filesz = m->p_size;
-                     else
-                       abort ();
-                     p->p_vaddr = lp->p_vaddr;
-                     p->p_offset = lp->p_offset;
-                     p->p_memsz = p->p_filesz;
-                     p->p_align = 1;
-                   }
-                 else
-                   abort ();
-               }
-             else
-               p->p_offset = m->sections[0]->filepos;
+             p->p_offset = m->sections[0]->filepos;
            }
        }
-      else
+      else if (m->includes_filehdr)
        {
-         if (m->includes_filehdr)
-           {
-             p->p_vaddr = filehdr_vaddr;
-             if (! m->p_paddr_valid)
-               p->p_paddr = filehdr_paddr;
-           }
-         else if (m->includes_phdrs)
-           {
-             p->p_vaddr = phdrs_vaddr;
-             if (! m->p_paddr_valid)
-               p->p_paddr = phdrs_paddr;
-           }
-         else if (p->p_type == PT_GNU_RELRO)
-           {
-             Elf_Internal_Phdr *lp;
-
-             for (lp = phdrs; lp < phdrs + count; ++lp)
-               {
-                 if (lp->p_type == PT_LOAD
-                     && lp->p_vaddr <= link_info->relro_end
-                     && lp->p_vaddr >= link_info->relro_start
-                     && (lp->p_vaddr + lp->p_filesz
-                         >= link_info->relro_end))
-                   break;
-               }
-
-             if (lp < phdrs + count
-                 && link_info->relro_end > lp->p_vaddr)
-               {
-                 p->p_vaddr = lp->p_vaddr;
-                 p->p_paddr = lp->p_paddr;
-                 p->p_offset = lp->p_offset;
-                 p->p_filesz = link_info->relro_end - lp->p_vaddr;
-                 p->p_memsz = p->p_filesz;
-                 p->p_align = 1;
-                 p->p_flags = (lp->p_flags & ~PF_W);
-               }
-             else
-               {
-                 memset (p, 0, sizeof *p);
-                 p->p_type = PT_NULL;
-               }
-           }
+         p->p_vaddr = filehdr_vaddr;
+         if (! m->p_paddr_valid)
+           p->p_paddr = filehdr_paddr;
+       }
+      else if (m->includes_phdrs)
+       {
+         p->p_vaddr = phdrs_vaddr;
+         if (! m->p_paddr_valid)
+           p->p_paddr = phdrs_paddr;
        }
     }
 
@@ -5559,19 +5565,32 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
          /* Offset the segment physical address from the lma
             to allow for space taken up by elf headers.  */
          if (map->includes_filehdr)
-           map->p_paddr -= iehdr->e_ehsize;
+           {
+             if (map->p_paddr >= iehdr->e_ehsize)
+               map->p_paddr -= iehdr->e_ehsize;
+             else
+               {
+                 map->includes_filehdr = FALSE;
+                 map->includes_phdrs = FALSE;
+               }
+           }
 
          if (map->includes_phdrs)
            {
-             map->p_paddr -= iehdr->e_phnum * iehdr->e_phentsize;
-
-             /* iehdr->e_phnum is just an estimate of the number
-                of program headers that we will need.  Make a note
-                here of the number we used and the segment we chose
-                to hold these headers, so that we can adjust the
-                offset when we know the correct value.  */
-             phdr_adjust_num = iehdr->e_phnum;
-             phdr_adjust_seg = map;
+             if (map->p_paddr >= iehdr->e_phnum * iehdr->e_phentsize)
+               {
+                 map->p_paddr -= iehdr->e_phnum * iehdr->e_phentsize;
+
+                 /* iehdr->e_phnum is just an estimate of the number
+                    of program headers that we will need.  Make a note
+                    here of the number we used and the segment we chose
+                    to hold these headers, so that we can adjust the
+                    offset when we know the correct value.  */
+                 phdr_adjust_num = iehdr->e_phnum;
+                 phdr_adjust_seg = map;
+               }
+             else
+               map->includes_phdrs = FALSE;
            }
        }
 
@@ -5804,14 +5823,13 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
       map->p_align_valid = 1;
       map->p_vaddr_offset = 0;
 
-      if (map->p_type == PT_GNU_RELRO
-         && segment->p_filesz == segment->p_memsz)
+      if (map->p_type == PT_GNU_RELRO)
        {
          /* The PT_GNU_RELRO segment may contain the first a few
             bytes in the .got.plt section even if the whole .got.plt
             section isn't in the PT_GNU_RELRO segment.  We won't
             change the size of the PT_GNU_RELRO segment.  */
-         map->p_size = segment->p_filesz;
+         map->p_size = segment->p_memsz;
          map->p_size_valid = 1;
        }
 
@@ -5833,6 +5851,10 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
            phdr_included = TRUE;
        }
 
+      if (map->includes_filehdr && first_section)
+       /* We need to keep the space used by the headers fixed.  */
+       map->header_size = first_section->vma - segment->p_vaddr;
+      
       if (!map->includes_phdrs
          && !map->includes_filehdr
          && map->p_paddr_valid)
@@ -6001,7 +6023,7 @@ _bfd_elf_init_private_section_data (bfd *ibfd,
          if (elf_section_flags (isec) & SHF_GROUP)
            elf_section_flags (osec) |= SHF_GROUP;
          elf_next_in_group (osec) = elf_next_in_group (isec);
-         elf_group_name (osec) = elf_group_name (isec);
+         elf_section_data (osec)->group = elf_section_data (isec)->group;
        }
     }
 
@@ -6364,6 +6386,8 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"),
 
       if ((flags & BSF_THREAD_LOCAL) != 0)
        type = STT_TLS;
+      else if ((flags & BSF_GNU_INDIRECT_FUNCTION) != 0)
+       type = STT_GNU_IFUNC;
       else if ((flags & BSF_FUNCTION) != 0)
        type = STT_FUNC;
       else if ((flags & BSF_OBJECT) != 0)
@@ -6397,9 +6421,8 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"),
          if (type == STT_OBJECT)
            sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_COMMON);
          else
-#else
-           sym.st_info = ELF_ST_INFO (STB_GLOBAL, type);
 #endif
+           sym.st_info = ELF_ST_INFO (STB_GLOBAL, type);
        }
       else if (bfd_is_und_section (syms[idx]->section))
        sym.st_info = ELF_ST_INFO (((flags & BSF_WEAK)
@@ -6414,6 +6437,8 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"),
 
          if (flags & BSF_LOCAL)
            bind = STB_LOCAL;
+         else if (flags & BSF_GNU_UNIQUE)
+           bind = STB_GNU_UNIQUE;
          else if (flags & BSF_WEAK)
            bind = STB_WEAK;
          else if (flags & BSF_GLOBAL)
@@ -7014,7 +7039,7 @@ _bfd_elf_set_arch_mach (bfd *abfd,
    for error reporting.  */
 
 static bfd_boolean
-elf_find_function (bfd *abfd ATTRIBUTE_UNUSED,
+elf_find_function (bfd *abfd,
                   asection *section,
                   asymbol **symbols,
                   bfd_vma offset,
@@ -7034,6 +7059,7 @@ elf_find_function (bfd *abfd ATTRIBUTE_UNUSED,
      make a better choice of file name for local symbols by ignoring
      file symbols appearing after a given local symbol.  */
   enum { nothing_seen, symbol_seen, file_after_symbol_seen } state;
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   filename = NULL;
   func = NULL;
@@ -7044,20 +7070,22 @@ elf_find_function (bfd *abfd ATTRIBUTE_UNUSED,
   for (p = symbols; *p != NULL; p++)
     {
       elf_symbol_type *q;
+      unsigned int type;
 
       q = (elf_symbol_type *) *p;
 
-      switch (ELF_ST_TYPE (q->internal_elf_sym.st_info))
+      type = ELF_ST_TYPE (q->internal_elf_sym.st_info);
+      switch (type)
        {
-       default:
-         break;
        case STT_FILE:
          file = &q->symbol;
          if (state == symbol_seen)
            state = file_after_symbol_seen;
          continue;
+       default:
+         if (!bed->is_function_type (type))
+           break;
        case STT_NOTYPE:
-       case STT_FUNC:
          if (bfd_get_section (&q->symbol) == section
              && q->symbol.value >= low_func
              && q->symbol.value <= offset)
@@ -7836,7 +7864,7 @@ elfcore_grok_win32pstatus (bfd *abfd, Elf_Internal_Note *note)
       /* Make a ".module/xxxxxxxx" section.  */
       /* module_info.base_address */
       base_addr = bfd_get_32 (abfd, note->descdata + 4);
-      sprintf (buf, ".module/%08lx", (long) base_addr);
+      sprintf (buf, ".module/%08lx", (unsigned long) base_addr);
 
       len = strlen (buf) + 1;
       name = bfd_alloc (abfd, len);
@@ -8070,6 +8098,70 @@ elfcore_grok_netbsd_note (bfd *abfd, Elf_Internal_Note *note)
     /* NOTREACHED */
 }
 
+static bfd_boolean
+elfcore_grok_openbsd_procinfo (bfd *abfd, Elf_Internal_Note *note)
+{
+  /* Signal number at offset 0x08. */
+  elf_tdata (abfd)->core_signal
+    = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x08);
+
+  /* Process ID at offset 0x20. */
+  elf_tdata (abfd)->core_pid
+    = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x20);
+
+  /* Command name at 0x48 (max 32 bytes, including nul). */
+  elf_tdata (abfd)->core_command
+    = _bfd_elfcore_strndup (abfd, note->descdata + 0x48, 31);
+
+  return TRUE;
+}
+
+static bfd_boolean
+elfcore_grok_openbsd_note (bfd *abfd, Elf_Internal_Note *note)
+{
+  if (note->type == NT_OPENBSD_PROCINFO)
+    return elfcore_grok_openbsd_procinfo (abfd, note);
+
+  if (note->type == NT_OPENBSD_REGS)
+    return elfcore_make_note_pseudosection (abfd, ".reg", note);
+
+  if (note->type == NT_OPENBSD_FPREGS)
+    return elfcore_make_note_pseudosection (abfd, ".reg2", note);
+
+  if (note->type == NT_OPENBSD_XFPREGS)
+    return elfcore_make_note_pseudosection (abfd, ".reg-xfp", note);
+
+  if (note->type == NT_OPENBSD_AUXV)
+    {
+      asection *sect = bfd_make_section_anyway_with_flags (abfd, ".auxv",
+                                                          SEC_HAS_CONTENTS);
+
+      if (sect == NULL)
+       return FALSE;
+      sect->size = note->descsz;
+      sect->filepos = note->descpos;
+      sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
+
+      return TRUE;
+    }
+
+  if (note->type == NT_OPENBSD_WCOOKIE)
+    {
+      asection *sect = bfd_make_section_anyway_with_flags (abfd, ".wcookie",
+                                                          SEC_HAS_CONTENTS);
+
+      if (sect == NULL)
+       return FALSE;
+      sect->size = note->descsz;
+      sect->filepos = note->descpos;
+      sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
+
+      return TRUE;
+    }
+
+  return TRUE;
+}
+
 static bfd_boolean
 elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, long *tid)
 {
@@ -8557,6 +8649,11 @@ elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
              if (! elfcore_grok_netbsd_note (abfd, &in))
                return FALSE;
            }
+         else if (CONST_STRNEQ (in.namedata, "OpenBSD"))
+           {
+             if (! elfcore_grok_openbsd_note (abfd, &in))
+               return FALSE;
+           }
          else if (CONST_STRNEQ (in.namedata, "QNX"))
            {
              if (! elfcore_grok_nto_note (abfd, &in))
@@ -8796,7 +8893,7 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd,
 
   relplt_name = bed->relplt_name;
   if (relplt_name == NULL)
-    relplt_name = bed->default_use_rela_p ? ".rela.plt" : ".rel.plt";
+    relplt_name = bed->rela_plts_and_copies_p ? ".rela.plt" : ".rel.plt";
   relplt = bfd_get_section_by_name (abfd, relplt_name);
   if (relplt == NULL)
     return 0;
@@ -8818,7 +8915,17 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd,
   size = count * sizeof (asymbol);
   p = relplt->relocation;
   for (i = 0; i < count; i++, p += bed->s->int_rels_per_ext_rel)
-    size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt");
+    {
+      size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt");
+      if (p->addend != 0)
+       {
+#ifdef BFD64
+         size += sizeof ("+0x") - 1 + 8 + 8 * (bed->s->elfclass == ELFCLASS64);
+#else
+         size += sizeof ("+0x") - 1 + 8;
+#endif
+       }
+    }
 
   s = *ret = bfd_malloc (size);
   if (s == NULL)
@@ -8849,6 +8956,19 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd,
       len = strlen ((*p->sym_ptr_ptr)->name);
       memcpy (names, (*p->sym_ptr_ptr)->name, len);
       names += len;
+      if (p->addend != 0)
+       {
+         char buf[30], *a;
+         int len;
+         memcpy (names, "+0x", sizeof ("+0x") - 1);
+         names += sizeof ("+0x") - 1;
+         bfd_sprintf_vma (abfd, buf, p->addend);
+         for (a = buf; *a == '0'; ++a)
+           ;
+         len = strlen (a);
+         memcpy (names, a, len);
+         names += len;
+       }
       memcpy (names, "@plt", sizeof ("@plt"));
       names += sizeof ("@plt");
       ++s, ++n;
@@ -8871,15 +8991,23 @@ _bfd_elf_set_osabi (bfd * abfd,
   i_ehdrp = elf_elfheader (abfd);
 
   i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
+
+  /* To make things simpler for the loader on Linux systems we set the
+     osabi field to ELFOSABI_LINUX if the binary contains symbols of
+     the STT_GNU_IFUNC type.  */
+  if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE
+      && elf_tdata (abfd)->has_ifunc_symbols)
+    i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_LINUX;
 }
 
 
 /* Return TRUE for ELF symbol types that represent functions.
    This is the default version of this function, which is sufficient for
-   most targets.  It returns true if TYPE is STT_FUNC.  */
+   most targets.  It returns true if TYPE is STT_FUNC or STT_GNU_IFUNC.  */
 
 bfd_boolean
 _bfd_elf_is_function_type (unsigned int type)
 {
-  return (type == STT_FUNC);
+  return (type == STT_FUNC
+         || type == STT_GNU_IFUNC);
 }
This page took 0.067419 seconds and 4 git commands to generate.