include/elf/
[deliverable/binutils-gdb.git] / bfd / elf.c
index d215144386a33f9870d53e5ffc835b63aadcc0ec..5ca43ebb4cbab8b04f9a275408f5e7c223f3013f 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1,7 +1,7 @@
 /* ELF executable support for BFD.
 
    Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -226,26 +226,36 @@ bfd_elf_gnu_hash (const char *namearg)
   return h & 0xffffffff;
 }
 
+/* Create a tdata field OBJECT_SIZE bytes in length, zeroed out and with
+   the object_id field of an elf_obj_tdata field set to OBJECT_ID.  */
 bfd_boolean
-bfd_elf_mkobject (bfd *abfd)
+bfd_elf_allocate_object (bfd *abfd,
+                        size_t object_size,
+                        enum elf_object_id object_id)
 {
+  BFD_ASSERT (object_size >= sizeof (struct elf_obj_tdata));
+  abfd->tdata.any = bfd_zalloc (abfd, object_size);
   if (abfd->tdata.any == NULL)
-    {
-      abfd->tdata.any = bfd_zalloc (abfd, sizeof (struct elf_obj_tdata));
-      if (abfd->tdata.any == NULL)
-       return FALSE;
-    }
-
-  elf_tdata (abfd)->program_header_size = (bfd_size_type) -1;
+    return FALSE;
 
+  elf_object_id (abfd) = object_id;
+  elf_program_header_size (abfd) = (bfd_size_type) -1;
   return TRUE;
 }
 
+
+bfd_boolean
+bfd_elf_make_generic_object (bfd *abfd)
+{
+  return bfd_elf_allocate_object (abfd, sizeof (struct elf_obj_tdata),
+                                 GENERIC_ELF_TDATA);
+}
+
 bfd_boolean
 bfd_elf_mkcorefile (bfd *abfd)
 {
   /* I think this can be done just like an object file.  */
-  return bfd_elf_mkobject (abfd);
+  return bfd_elf_make_generic_object (abfd);
 }
 
 char *
@@ -326,7 +336,9 @@ bfd_elf_string_from_elf_section (bfd *abfd,
    SYMCOUNT specifies the number of symbols to read, starting from
    symbol SYMOFFSET.  If any of INTSYM_BUF, EXTSYM_BUF or EXTSHNDX_BUF
    are non-NULL, they are used to store the internal symbols, external
-   symbols, and symbol section index extensions, respectively.  */
+   symbols, and symbol section index extensions, respectively.
+   Returns a pointer to the internal symbol buffer (malloced if necessary)
+   or NULL if there were no symbols or some kind of problem.  */
 
 Elf_Internal_Sym *
 bfd_elf_get_elf_syms (bfd *ibfd,
@@ -349,6 +361,9 @@ bfd_elf_get_elf_syms (bfd *ibfd,
   bfd_size_type amt;
   file_ptr pos;
 
+  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
+    abort ();
+
   if (symcount == 0)
     return intsym_buf;
 
@@ -442,8 +457,7 @@ bfd_elf_sym_name (bfd *abfd,
 
   if (iname == 0 && ELF_ST_TYPE (isym->st_info) == STT_SECTION
       /* Check for a bogus st_shndx to avoid crashing.  */
-      && isym->st_shndx < elf_numsections (abfd)
-      && !(isym->st_shndx >= SHN_LORESERVE && isym->st_shndx <= SHN_HIRESERVE))
+      && isym->st_shndx < elf_numsections (abfd))
     {
       iname = elf_elfsections (abfd)[isym->st_shndx]->sh_name;
       shindex = elf_elfheader (abfd)->e_shstrndx;
@@ -480,6 +494,8 @@ group_signature (bfd *abfd, Elf_Internal_Shdr *ghdr)
 
   /* First we need to ensure the symbol table is available.  Make sure
      that it is a symbol table section.  */
+  if (ghdr->sh_link >= elf_numsections (abfd))
+    return NULL;
   hdr = elf_elfsections (abfd) [ghdr->sh_link];
   if (hdr->sh_type != SHT_SYMTAB
       || ! bfd_section_from_shdr (abfd, ghdr->sh_link))
@@ -698,8 +714,7 @@ _bfd_elf_setup_sections (bfd *abfd)
             get the situation where elfsec is 0.  */
          if (elfsec == 0)
            {
-             const struct elf_backend_data *bed
-               = get_elf_backend_data (abfd);
+             const struct elf_backend_data *bed = get_elf_backend_data (abfd);
              if (bed->link_order_error_handler)
                bed->link_order_error_handler
                  (_("%B: warning: sh_link not set for section `%A'"),
@@ -707,14 +722,17 @@ _bfd_elf_setup_sections (bfd *abfd)
            }
          else
            {
-             asection *link;
+             asection *link = NULL;
 
-             this_hdr = elf_elfsections (abfd)[elfsec];
+             if (elfsec < elf_numsections (abfd))
+               {
+                 this_hdr = elf_elfsections (abfd)[elfsec];
+                 link = this_hdr->bfd_section;
+               }
 
              /* PR 1991, 2008:
                 Some strip/objcopy may leave an incorrect value in
                 sh_link.  We don't want to proceed.  */
-             link = this_hdr->bfd_section;
              if (link == NULL)
                {
                  (*_bfd_error_handler)
@@ -1165,7 +1183,7 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
   s = bfd_get_section_by_name (abfd, ".dynamic");
   if (s != NULL)
     {
-      int elfsec;
+      unsigned int elfsec;
       unsigned long shlink;
       bfd_byte *extdyn, *extdynend;
       size_t extdynsize;
@@ -1177,7 +1195,7 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
        goto error_return;
 
       elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
-      if (elfsec == -1)
+      if (elfsec == SHN_BAD)
        goto error_return;
       shlink = elf_elfsections (abfd)[elfsec]->sh_link;
 
@@ -1189,9 +1207,10 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
       for (; extdyn < extdynend; extdyn += extdynsize)
        {
          Elf_Internal_Dyn dyn;
-         const char *name;
+         const char *name = "";
          char ab[20];
          bfd_boolean stringp;
+         const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
          (*swap_dyn_in) (abfd, extdyn, &dyn);
 
@@ -1202,8 +1221,14 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
          switch (dyn.d_tag)
            {
            default:
-             sprintf (ab, "0x%lx", (unsigned long) dyn.d_tag);
-             name = ab;
+             if (bed->elf_backend_get_target_dtag)
+               name = (*bed->elf_backend_get_target_dtag) (dyn.d_tag);
+
+             if (!strcmp (name, ""))
+               {
+                 sprintf (ab, "0x%lx", (unsigned long) dyn.d_tag);
+                 name = ab;
+               }
              break;
 
            case DT_NEEDED: name = "NEEDED"; stringp = TRUE; break;
@@ -1266,7 +1291,7 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
            case DT_GNU_HASH: name = "GNU_HASH"; break;
            }
 
-         fprintf (f, "  %-11s ", name);
+         fprintf (f, "  %-20s ", name);
          if (! stringp)
            fprintf (f, "0x%lx", (unsigned long) dyn.d_un.d_val);
          else
@@ -1496,17 +1521,22 @@ _bfd_elf_stringtab_init (void)
 bfd_boolean
 bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
 {
-  Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[shindex];
-  Elf_Internal_Ehdr *ehdr = elf_elfheader (abfd);
-  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  Elf_Internal_Shdr *hdr;
+  Elf_Internal_Ehdr *ehdr;
+  const struct elf_backend_data *bed;
   const char *name;
 
-  name = bfd_elf_string_from_elf_section (abfd,
-                                         elf_elfheader (abfd)->e_shstrndx,
+  if (shindex >= elf_numsections (abfd))
+    return FALSE;
+
+  hdr = elf_elfsections (abfd)[shindex];
+  ehdr = elf_elfheader (abfd);
+  name = bfd_elf_string_from_elf_section (abfd, ehdr->e_shstrndx,
                                          hdr->sh_name);
   if (name == NULL)
     return FALSE;
 
+  bed = get_elf_backend_data (abfd);
   switch (hdr->sh_type)
     {
     case SHT_NULL:
@@ -1707,8 +1737,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
          return FALSE;
 
        /* Check for a bogus link to avoid crashing.  */
-       if ((hdr->sh_link >= SHN_LORESERVE && hdr->sh_link <= SHN_HIRESERVE)
-           || hdr->sh_link >= num_sec)
+       if (hdr->sh_link >= num_sec)
          {
            ((*_bfd_error_handler)
             (_("%B: invalid link %lu for reloc section %s (index %u)"),
@@ -1762,7 +1791,6 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
           section, an invalid section, or another reloc section.  */
        if (hdr->sh_link != elf_onesymtab (abfd)
            || hdr->sh_info == SHN_UNDEF
-           || (hdr->sh_info >= SHN_LORESERVE && hdr->sh_info <= SHN_HIRESERVE)
            || hdr->sh_info >= num_sec
            || elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_REL
            || elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_RELA)
@@ -2497,7 +2525,7 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg)
         non-bss input sections to bss output sections, or emit data
         to a bss output section via a linker script.  */
       (*_bfd_error_handler)
-       (_("section `%A' type changed to PROGBITS"), asect);
+       (_("warning: section `%A' type changed to PROGBITS"), asect);
       this_hdr->sh_type = sh_type;
     }
 
@@ -2749,11 +2777,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
                  abfd->section_count--;
                }
              else
-               {
-                 if (section_number == SHN_LORESERVE)
-                   section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
-                 d->this_idx = section_number++;
-               }
+               d->this_idx = section_number++;
            }
        }
     }
@@ -2763,26 +2787,18 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
       d = elf_section_data (sec);
 
       if (d->this_hdr.sh_type != SHT_GROUP)
-       {
-         if (section_number == SHN_LORESERVE)
-           section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
-         d->this_idx = section_number++;
-       }
+       d->this_idx = section_number++;
       _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->this_hdr.sh_name);
       if ((sec->flags & SEC_RELOC) == 0)
        d->rel_idx = 0;
       else
        {
-         if (section_number == SHN_LORESERVE)
-           section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
          d->rel_idx = section_number++;
          _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr.sh_name);
        }
 
       if (d->rel_hdr2)
        {
-         if (section_number == SHN_LORESERVE)
-           section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
          d->rel_idx2 = section_number++;
          _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr2->sh_name);
        }
@@ -2790,22 +2806,16 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
        d->rel_idx2 = 0;
     }
 
-  if (section_number == SHN_LORESERVE)
-    section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
   t->shstrtab_section = section_number++;
   _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)
     {
-      if (section_number == SHN_LORESERVE)
-       section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
       t->symtab_section = section_number++;
       _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name);
-      if (section_number > SHN_LORESERVE - 2)
+      if (section_number > ((SHN_LORESERVE - 2) & 0xFFFF))
        {
-         if (section_number == SHN_LORESERVE)
-           section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
          t->symtab_shndx_section = section_number++;
          t->symtab_shndx_hdr.sh_name
            = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
@@ -2813,8 +2823,6 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
          if (t->symtab_shndx_hdr.sh_name == (unsigned int) -1)
            return FALSE;
        }
-      if (section_number == SHN_LORESERVE)
-       section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
       t->strtab_section = section_number++;
       _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->strtab_hdr.sh_name);
     }
@@ -2824,8 +2832,6 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
 
   elf_numsections (abfd) = section_number;
   elf_elfheader (abfd)->e_shnum = section_number;
-  if (section_number > SHN_LORESERVE)
-    elf_elfheader (abfd)->e_shnum -= SHN_HIRESERVE + 1 - SHN_LORESERVE;
 
   /* Set up the list of section header pointers, in agreement with the
      indices.  */
@@ -2846,7 +2852,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
   if (bfd_get_symcount (abfd) > 0)
     {
       i_shdrp[t->symtab_section] = &t->symtab_hdr;
-      if (elf_numsections (abfd) > SHN_LORESERVE)
+      if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF))
        {
          i_shdrp[t->symtab_shndx_section] = &t->symtab_shndx_hdr;
          t->symtab_shndx_hdr.sh_link = t->symtab_section;
@@ -3426,6 +3432,29 @@ get_program_header_size (bfd *abfd, struct bfd_link_info *info)
   return segs * bed->s->sizeof_phdr;
 }
 
+/* Find the segment that contains the output_section of section.  */
+
+Elf_Internal_Phdr *
+_bfd_elf_find_segment_containing_section (bfd * abfd, asection * section)
+{
+  struct elf_segment_map *m;
+  Elf_Internal_Phdr *p;
+
+  for (m = elf_tdata (abfd)->segment_map,
+        p = elf_tdata (abfd)->phdr;
+       m != NULL;
+       m = m->next, p++)
+    {
+      int i;
+
+      for (i = m->count - 1; i >= 0; i--)
+       if (m->sections[i] == section)
+         return p;
+    }
+
+  return NULL;
+}
+
 /* Create a mapping from a set of sections to a program segment.  */
 
 static struct elf_segment_map *
@@ -4246,6 +4275,10 @@ assign_file_positions_for_load_sections (bfd *abfd,
          bfd_set_error (bfd_error_bad_value);
          return FALSE;
        }
+      /* Set the note section type to SHT_NOTE.  */
+      else if (p->p_type == PT_NOTE)
+       for (i = 0; i < m->count; i++)
+         elf_section_type (m->sections[i]) = SHT_NOTE;
 
       p->p_offset = 0;
       p->p_filesz = 0;
@@ -4511,12 +4544,6 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
        hdr->sh_offset = -1;
       else
        off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
-
-      if (i == SHN_LORESERVE - 1)
-       {
-         i += SHN_HIRESERVE + 1 - SHN_LORESERVE;
-         hdrpp += SHN_HIRESERVE + 1 - SHN_LORESERVE;
-       }
     }
 
   /* Now that we have set the section file positions, we can set up
@@ -4713,12 +4740,6 @@ assign_file_positions_except_relocs (bfd *abfd,
            }
          else
            off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
-
-         if (i == SHN_LORESERVE - 1)
-           {
-             i += SHN_HIRESERVE + 1 - SHN_LORESERVE;
-             hdrpp += SHN_HIRESERVE + 1 - SHN_LORESERVE;
-           }
        }
     }
   else
@@ -4764,12 +4785,10 @@ prep_headers (bfd *abfd)
 {
   Elf_Internal_Ehdr *i_ehdrp;  /* Elf file header, internal form */
   Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */
-  Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */
   struct elf_strtab_hash *shstrtab;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   i_ehdrp = elf_elfheader (abfd);
-  i_shdrp = elf_elfsections (abfd);
 
   shstrtab = _bfd_elf_strtab_init ();
   if (shstrtab == NULL)
@@ -4914,8 +4933,6 @@ _bfd_elf_write_object_contents (bfd *abfd)
              || bfd_bwrite (i_shdrp[count]->contents, amt, abfd) != amt)
            return FALSE;
        }
-      if (count == SHN_LORESERVE - 1)
-       count += SHN_HIRESERVE + 1 - SHN_LORESERVE;
     }
 
   /* Write out the section header names.  */
@@ -4947,11 +4964,11 @@ _bfd_elf_write_corefile_contents (bfd *abfd)
 
 /* Given a section, search the header to find them.  */
 
-int
+unsigned int
 _bfd_elf_section_from_bfd_section (bfd *abfd, struct bfd_section *asect)
 {
   const struct elf_backend_data *bed;
-  int index;
+  unsigned int index;
 
   if (elf_section_data (asect) != NULL
       && elf_section_data (asect)->this_idx != 0)
@@ -4964,7 +4981,7 @@ _bfd_elf_section_from_bfd_section (bfd *abfd, struct bfd_section *asect)
   else if (bfd_is_und_section (asect))
     index = SHN_UNDEF;
   else
-    index = -1;
+    index = SHN_BAD;
 
   bed = get_elf_backend_data (abfd);
   if (bed->elf_backend_section_from_bfd_section)
@@ -4975,7 +4992,7 @@ _bfd_elf_section_from_bfd_section (bfd *abfd, struct bfd_section *asect)
        return retval;
     }
 
-  if (index == -1)
+  if (index == SHN_BAD)
     bfd_set_error (bfd_error_nonrepresentable_section);
 
   return index;
@@ -5090,15 +5107,22 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
    && (section->lma + SECTION_SIZE (section, segment)                  \
        <= SEGMENT_END (segment, base)))
 
-  /* Special case: corefile "NOTE" section containing regs, prpsinfo etc.  */
-#define IS_COREFILE_NOTE(p, s)                                         \
+  /* Handle PT_NOTE segment.  */
+#define IS_NOTE(p, s)                                                  \
   (p->p_type == PT_NOTE                                                        \
-   && bfd_get_format (ibfd) == bfd_core                                        \
-   && s->vma == 0 && s->lma == 0                                       \
+   && elf_section_type (s) == SHT_NOTE                                 \
    && (bfd_vma) s->filepos >= p->p_offset                              \
    && ((bfd_vma) s->filepos + s->size                                  \
        <= p->p_offset + p->p_filesz))
 
+  /* Special case: corefile "NOTE" section containing regs, prpsinfo
+     etc.  */
+#define IS_COREFILE_NOTE(p, s)                                         \
+  (IS_NOTE (p, s)                                                      \
+   && bfd_get_format (ibfd) == bfd_core                                        \
+   && s->vma == 0                                                      \
+   && s->lma == 0)
+
   /* The complicated case when p_vaddr is 0 is to handle the Solaris
      linker, which generates a PT_INTERP section with p_vaddr and
      p_memsz set to 0.  */
@@ -5117,7 +5141,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
      A section will be included if:
        1. It is within the address space of the segment -- we use the LMA
          if that is set for the segment and the VMA otherwise,
-       2. It is an allocated segment,
+       2. It is an allocated section or a NOTE section in a PT_NOTE
+         segment.         
        3. There is an output section associated with it,
        4. The section has not already been allocated to a previous segment.
        5. PT_GNU_STACK segments do not include any sections.
@@ -5130,7 +5155,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
       ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr)       \
       : IS_CONTAINED_BY_VMA (section, segment))                                \
      && (section->flags & SEC_ALLOC) != 0)                             \
-    || IS_COREFILE_NOTE (segment, section))                            \
+    || IS_NOTE (segment, section))                                     \
    && segment->p_type != PT_GNU_STACK                                  \
    && (segment->p_type != PT_TLS                                       \
        || (section->flags & SEC_THREAD_LOCAL))                         \
@@ -5144,7 +5169,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
           : segment->p_vaddr != section->vma)                          \
        || (strcmp (bfd_get_section_name (ibfd, section), ".dynamic")   \
           == 0))                                                       \
-   && ! section->segment_mark)
+   && !section->segment_mark)
 
 /* If the output section of a section in the input segment is NULL,
    it is removed from the corresponding output segment.   */
@@ -5202,12 +5227,12 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
        }
 
       /* Determine if this segment overlaps any previous segments.  */
-      for (j = 0, segment2 = elf_tdata (ibfd)->phdr; j < i; j++, segment2 ++)
+      for (j = 0, segment2 = elf_tdata (ibfd)->phdr; j < i; j++, segment2++)
        {
          bfd_signed_vma extra_length;
 
          if (segment2->p_type != PT_LOAD
-             || ! SEGMENT_OVERLAPS (segment, segment2))
+             || !SEGMENT_OVERLAPS (segment, segment2))
            continue;
 
          /* Merge the two segments together.  */
@@ -5215,13 +5240,12 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
            {
              /* Extend SEGMENT2 to include SEGMENT and then delete
                 SEGMENT.  */
-             extra_length =
-               SEGMENT_END (segment, segment->p_vaddr)
-               - SEGMENT_END (segment2, segment2->p_vaddr);
+             extra_length = (SEGMENT_END (segment, segment->p_vaddr)
+                             - SEGMENT_END (segment2, segment2->p_vaddr));
 
              if (extra_length > 0)
                {
-                 segment2->p_memsz  += extra_length;
+                 segment2->p_memsz += extra_length;
                  segment2->p_filesz += extra_length;
                }
 
@@ -5236,13 +5260,12 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
            {
              /* Extend SEGMENT to include SEGMENT2 and then delete
                 SEGMENT2.  */
-             extra_length =
-               SEGMENT_END (segment2, segment2->p_vaddr)
-               - SEGMENT_END (segment, segment->p_vaddr);
+             extra_length = (SEGMENT_END (segment2, segment2->p_vaddr)
+                             - SEGMENT_END (segment, segment->p_vaddr));
 
              if (extra_length > 0)
                {
-                 segment->p_memsz  += extra_length;
+                 segment->p_memsz += extra_length;
                  segment->p_filesz += extra_length;
                }
 
@@ -5254,17 +5277,19 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
   /* The second scan attempts to assign sections to segments.  */
   for (i = 0, segment = elf_tdata (ibfd)->phdr;
        i < num_segments;
-       i ++, segment ++)
-    {
-      unsigned int  section_count;
-      asection **   sections;
-      asection *    output_section;
-      unsigned int  isec;
-      bfd_vma       matching_lma;
-      bfd_vma       suggested_lma;
-      unsigned int  j;
+       i++, segment++)
+    {
+      unsigned int section_count;
+      asection **sections;
+      asection *output_section;
+      unsigned int isec;
+      bfd_vma matching_lma;
+      bfd_vma suggested_lma;
+      unsigned int j;
       bfd_size_type amt;
-      asection *    first_section;
+      asection *first_section;
+      bfd_boolean first_matching_lma;
+      bfd_boolean first_suggested_lma;
 
       if (segment->p_type == PT_NULL)
        continue;
@@ -5296,9 +5321,9 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
 
       /* Initialise the fields of the segment map.  Default to
         using the physical address of the segment in the input BFD.  */
-      map->next          = NULL;
-      map->p_type        = segment->p_type;
-      map->p_flags       = segment->p_flags;
+      map->next = NULL;
+      map->p_type = segment->p_type;
+      map->p_flags = segment->p_flags;
       map->p_flags_valid = 1;
 
       /* If the first section in the input segment is removed, there is
@@ -5314,10 +5339,9 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
         and if it contains the program headers themselves.  */
       map->includes_filehdr = (segment->p_offset == 0
                               && segment->p_filesz >= iehdr->e_ehsize);
-
       map->includes_phdrs = 0;
 
-      if (! phdr_included || segment->p_type != PT_LOAD)
+      if (!phdr_included || segment->p_type != PT_LOAD)
        {
          map->includes_phdrs =
            (segment->p_offset <= (bfd_vma) iehdr->e_phoff
@@ -5336,9 +5360,9 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
             something.  They are allowed by the ELF spec however, so only
             a warning is produced.  */
          if (segment->p_type == PT_LOAD)
-           (*_bfd_error_handler)
-             (_("%B: warning: Empty loadable segment detected, is this intentional ?\n"),
-              ibfd);
+           (*_bfd_error_handler) (_("%B: warning: Empty loadable segment"
+                                    " detected, is this intentional ?\n"),
+                                  ibfd);
 
          map->count = 0;
          *pointer_to_map = map;
@@ -5390,16 +5414,22 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
       isec = 0;
       matching_lma = 0;
       suggested_lma = 0;
+      first_matching_lma = TRUE;
+      first_suggested_lma = TRUE;
 
-      for (j = 0, section = ibfd->sections;
+      for (section = ibfd->sections;
           section != NULL;
           section = section->next)
+       if (section == first_section)
+         break;
+
+      for (j = 0; section != NULL; section = section->next)
        {
          if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed))
            {
              output_section = section->output_section;
 
-             sections[j ++] = section;
+             sections[j++] = section;
 
              /* The Solaris native linker always sets p_paddr to 0.
                 We try to catch that case here, and set it to the
@@ -5407,36 +5437,45 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
                 p_paddr be left as zero.  */
              if (segment->p_paddr == 0
                  && segment->p_vaddr != 0
-                 && (! bed->want_p_paddr_set_to_zero)
+                 && !bed->want_p_paddr_set_to_zero
                  && isec == 0
                  && output_section->lma != 0
-                 && (output_section->vma == (segment->p_vaddr
-                                             + (map->includes_filehdr
-                                                ? iehdr->e_ehsize
-                                                : 0)
-                                             + (map->includes_phdrs
-                                                ? (iehdr->e_phnum
-                                                   * iehdr->e_phentsize)
-                                                : 0))))
+                 && output_section->vma == (segment->p_vaddr
+                                            + (map->includes_filehdr
+                                               ? iehdr->e_ehsize
+                                               : 0)
+                                            + (map->includes_phdrs
+                                               ? (iehdr->e_phnum
+                                                  * iehdr->e_phentsize)
+                                               : 0)))
                map->p_paddr = segment->p_vaddr;
 
              /* Match up the physical address of the segment with the
                 LMA address of the output section.  */
              if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr)
                  || IS_COREFILE_NOTE (segment, section)
-                 || (bed->want_p_paddr_set_to_zero &&
-                     IS_CONTAINED_BY_VMA (output_section, segment)))
+                 || (bed->want_p_paddr_set_to_zero
+                     && IS_CONTAINED_BY_VMA (output_section, segment)))
                {
-                 if (matching_lma == 0 || output_section->lma < matching_lma)
-                   matching_lma = output_section->lma;
+                 if (first_matching_lma || output_section->lma < matching_lma)
+                   {
+                     matching_lma = output_section->lma;
+                     first_matching_lma = FALSE;
+                   }
 
                  /* We assume that if the section fits within the segment
                     then it does not overlap any other section within that
                     segment.  */
-                 map->sections[isec ++] = output_section;
+                 map->sections[isec++] = output_section;
+               }
+             else if (first_suggested_lma)
+               {
+                 suggested_lma = output_section->lma;
+                 first_suggested_lma = FALSE;
                }
-             else if (suggested_lma == 0)
-               suggested_lma = output_section->lma;
+
+             if (j == section_count)
+               break;
            }
        }
 
@@ -5454,7 +5493,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
          *pointer_to_map = map;
          pointer_to_map = &map->next;
 
-         if (matching_lma != map->p_paddr
+         if (!bed->want_p_paddr_set_to_zero
+             && matching_lma != map->p_paddr
              && !map->includes_filehdr && !map->includes_phdrs)
            /* There is some padding before the first section in the
               segment.  So, we must account for that in the output
@@ -5466,7 +5506,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
        }
       else
        {
-         if (matching_lma != 0)
+         if (!first_matching_lma)
            {
              /* At least one section fits inside the current segment.
                 Keep it, but modify its physical address to match the
@@ -5512,6 +5552,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
        {
          map->count = 0;
          suggested_lma = 0;
+         first_suggested_lma = TRUE;
 
          /* Fill the current segment with sections that fit.  */
          for (j = 0; j < section_count; j++)
@@ -5533,17 +5574,17 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
                      /* If the first section in a segment does not start at
                         the beginning of the segment, then something is
                         wrong.  */
-                     if (output_section->lma !=
-                         (map->p_paddr
-                          + (map->includes_filehdr ? iehdr->e_ehsize : 0)
-                          + (map->includes_phdrs
-                             ? iehdr->e_phnum * iehdr->e_phentsize
-                             : 0)))
+                     if (output_section->lma
+                         != (map->p_paddr
+                             + (map->includes_filehdr ? iehdr->e_ehsize : 0)
+                             + (map->includes_phdrs
+                                ? iehdr->e_phnum * iehdr->e_phentsize
+                                : 0)))
                        abort ();
                    }
                  else
                    {
-                     asection * prev_sec;
+                     asection *prev_sec;
 
                      prev_sec = map->sections[map->count - 1];
 
@@ -5553,11 +5594,14 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
                      if ((BFD_ALIGN (prev_sec->lma + prev_sec->size,
                                      maxpagesize)
                           < BFD_ALIGN (output_section->lma, maxpagesize))
-                         || ((prev_sec->lma + prev_sec->size)
+                         || (prev_sec->lma + prev_sec->size
                              > output_section->lma))
                        {
-                         if (suggested_lma == 0)
-                           suggested_lma = output_section->lma;
+                         if (first_suggested_lma)
+                           {
+                             suggested_lma = output_section->lma;
+                             first_suggested_lma = FALSE;
+                           }
 
                          continue;
                        }
@@ -5568,8 +5612,11 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
                  sections[j] = NULL;
                  section->segment_mark = TRUE;
                }
-             else if (suggested_lma == 0)
-               suggested_lma = output_section->lma;
+             else if (first_suggested_lma)
+               {
+                 suggested_lma = output_section->lma;
+                 first_suggested_lma = FALSE;
+               }
            }
 
          BFD_ASSERT (map->count > 0);
@@ -5595,14 +5642,14 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
              /* Initialise the fields of the segment map.  Set the physical
                 physical address to the LMA of the first section that has
                 not yet been assigned.  */
-             map->next             = NULL;
-             map->p_type           = segment->p_type;
-             map->p_flags          = segment->p_flags;
-             map->p_flags_valid    = 1;
-             map->p_paddr          = suggested_lma;
-             map->p_paddr_valid    = 1;
+             map->next = NULL;
+             map->p_type = segment->p_type;
+             map->p_flags = segment->p_flags;
+             map->p_flags_valid = 1;
+             map->p_paddr = suggested_lma;
+             map->p_paddr_valid = 1;
              map->includes_filehdr = 0;
-             map->includes_phdrs   = 0;
+             map->includes_phdrs = 0;
            }
        }
       while (isec < section_count);
@@ -5642,6 +5689,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
 #undef SECTION_SIZE
 #undef IS_CONTAINED_BY_VMA
 #undef IS_CONTAINED_BY_LMA
+#undef IS_NOTE
 #undef IS_COREFILE_NOTE
 #undef IS_SOLARIS_PT_INTERP
 #undef IS_SECTION_IN_INPUT_SEGMENT
@@ -5801,6 +5849,13 @@ copy_private_bfd_data (bfd *ibfd, bfd *obfd)
       asection *section, *osec;
       unsigned int i, num_segments;
       Elf_Internal_Shdr *this_hdr;
+      const struct elf_backend_data *bed;
+
+      bed = get_elf_backend_data (ibfd);
+
+      /* Regenerate the segment map if p_paddr is set to 0.  */
+      if (bed->want_p_paddr_set_to_zero)
+       goto rewrite;
 
       /* Initialize the segment mark field.  */
       for (section = obfd->sections; section != NULL;
@@ -6032,6 +6087,7 @@ _bfd_elf_copy_private_symbol_data (bfd *ibfd,
   osym = elf_symbol_from (obfd, osymarg);
 
   if (isym != NULL
+      && isym->internal_elf_sym.st_shndx != 0
       && osym != NULL
       && bfd_is_abs_section (isym->symbol.section))
     {
@@ -6189,7 +6245,7 @@ swap_out_syms (bfd *abfd,
       else
        {
          asection *sec = syms[idx]->section;
-         int shndx;
+         unsigned int shndx;
 
          if (sec->output_section)
            {
@@ -6236,7 +6292,7 @@ swap_out_syms (bfd *abfd,
            {
              shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
 
-             if (shndx == -1)
+             if (shndx == SHN_BAD)
                {
                  asection *sec2;
 
@@ -6260,7 +6316,7 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"),
                    }
 
                  shndx = _bfd_elf_section_from_bfd_section (abfd, sec2);
-                 BFD_ASSERT (shndx != -1);
+                 BFD_ASSERT (shndx != SHN_BAD);
                }
            }
 
@@ -6297,7 +6353,15 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"),
            sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
        }
       else if (bfd_is_com_section (syms[idx]->section))
-       sym.st_info = ELF_ST_INFO (STB_GLOBAL, type);
+       {
+#ifdef USE_STT_COMMON
+         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
+       }
       else if (bfd_is_und_section (syms[idx]->section))
        sym.st_info = ELF_ST_INFO (((flags & BSF_WEAK)
                                    ? STB_WEAK
@@ -7436,7 +7500,7 @@ elfcore_grok_prfpreg (bfd *abfd, Elf_Internal_Note *note)
 }
 
 /* Linux dumps the Intel SSE regs in a note named "LINUX" with a note
-   type of 5 (NT_PRXFPREG).  Just include the whole note's contents
+   type of NT_PRXFPREG.  Just include the whole note's contents
    literally.  */
 
 static bfd_boolean
@@ -7445,6 +7509,13 @@ elfcore_grok_prxfpreg (bfd *abfd, Elf_Internal_Note *note)
   return elfcore_make_note_pseudosection (abfd, ".reg-xfp", note);
 }
 
+static bfd_boolean
+elfcore_grok_ppc_vmx (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-ppc-vmx", note);
+}
+
+
 #if defined (HAVE_PRPSINFO_T)
 typedef prpsinfo_t   elfcore_psinfo_t;
 #if defined (HAVE_PRPSINFO32_T)                /* Sparc64 cross Sparc32 */
@@ -7792,6 +7863,13 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
       else
        return TRUE;
 
+    case NT_PPC_VMX:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_ppc_vmx (abfd, note);
+      else
+       return TRUE;
+
     case NT_PRPSINFO:
     case NT_PSINFO:
       if (bed->elf_backend_grok_psinfo)
@@ -8346,6 +8424,18 @@ elfcore_write_prxfpreg (bfd *abfd,
                             note_name, NT_PRXFPREG, xfpregs, size);
 }
 
+char *
+elfcore_write_ppc_vmx (bfd *abfd,
+                      char *buf,
+                      int *bufsiz,
+                      const void *ppc_vmx,
+                      int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                            note_name, NT_PPC_VMX, ppc_vmx, size);
+}
+
 static bfd_boolean
 elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
 {
@@ -8648,7 +8738,7 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd,
   names = (char *) (s + count);
   p = relplt->relocation;
   n = 0;
-  for (i = 0; i < count; i++, s++, p++)
+  for (i = 0; i < count; i++, p++)
     {
       size_t len;
       bfd_vma addr;
@@ -8665,12 +8755,13 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd,
       s->section = plt;
       s->value = addr - plt->vma;
       s->name = names;
+      s->udata.p = NULL;
       len = strlen ((*p->sym_ptr_ptr)->name);
       memcpy (names, (*p->sym_ptr_ptr)->name, len);
       names += len;
       memcpy (names, "@plt", sizeof ("@plt"));
       names += sizeof ("@plt");
-      ++n;
+      ++s, ++n;
     }
 
   return n;
This page took 0.058375 seconds and 4 git commands to generate.