* cache.c (cache_bread): Set bfd_error_file_truncated if EOF
[deliverable/binutils-gdb.git] / bfd / elf.c
index b5b51d02a3f4eef7655261c9c8ca2c257b5aaa8d..b5dd63686828ea1f48b22036ccbc7c0af6812edd 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.
 
@@ -326,7 +326,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 +351,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;
 
@@ -2497,7 +2502,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;
     }
 
@@ -3426,6 +3431,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 *
@@ -5090,15 +5118,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 +5152,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 +5166,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 +5180,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 +5238,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 +5251,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 +5271,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 +5288,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 +5332,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 +5350,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 +5371,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 +5425,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 +5448,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 (suggested_lma == 0)
-               suggested_lma = output_section->lma;
+             else if (first_suggested_lma)
+               {
+                 suggested_lma = output_section->lma;
+                 first_suggested_lma = FALSE;
+               }
+
+             if (j == section_count)
+               break;
            }
        }
 
@@ -5454,7 +5504,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 +5517,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 +5563,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 +5585,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 +5605,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 +5623,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 +5653,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 +5700,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 +5860,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 +6098,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))
     {
@@ -6297,7 +6364,11 @@ 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);
+       sym.st_info = ELF_ST_INFO (STB_GLOBAL,
+#ifdef USE_STT_COMMON
+                                  type == STT_OBJECT ? STT_COMMON :
+#endif
+                                  type);
       else if (bfd_is_und_section (syms[idx]->section))
        sym.st_info = ELF_ST_INFO (((flags & BSF_WEAK)
                                    ? STB_WEAK
@@ -7445,6 +7516,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 +7870,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 +8431,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 +8745,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 +8762,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.038324 seconds and 4 git commands to generate.