* elf-bfd.h (_bfd_elf_section_from_bfd_section): Update prototype.
[deliverable/binutils-gdb.git] / bfd / elf.c
index 7043f564d979cb104f7ecb92c99dee6ef6f5195e..c697e9e52e263e52e476943c8c47b61e6d942c77 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;
 
@@ -1165,7 +1180,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 +1192,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 +1204,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 +1218,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 +1288,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
@@ -2497,7 +2519,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 +3448,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 +4291,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;
@@ -4947,11 +4996,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 +5013,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 +5024,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 +5139,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 +5173,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 +5187,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))                         \
@@ -5392,9 +5449,13 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
       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))
            {
@@ -5444,6 +5505,9 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
                  suggested_lma = output_section->lma;
                  first_suggested_lma = FALSE;
                }
+
+             if (j == section_count)
+               break;
            }
        }
 
@@ -5461,7 +5525,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
@@ -5656,6 +5721,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
@@ -5815,6 +5881,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;
@@ -6046,6 +6119,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))
     {
@@ -6203,7 +6277,7 @@ swap_out_syms (bfd *abfd,
       else
        {
          asection *sec = syms[idx]->section;
-         int shndx;
+         unsigned int shndx;
 
          if (sec->output_section)
            {
@@ -6250,7 +6324,7 @@ swap_out_syms (bfd *abfd,
            {
              shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
 
-             if (shndx == -1)
+             if (shndx == SHN_BAD)
                {
                  asection *sec2;
 
@@ -6274,7 +6348,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);
                }
            }
 
@@ -6311,11 +6385,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,
+       {
 #ifdef USE_STT_COMMON
-                                  type == STT_OBJECT ? 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
-                                  type);
+       }
       else if (bfd_is_und_section (syms[idx]->section))
        sym.st_info = ELF_ST_INFO (((flags & BSF_WEAK)
                                    ? STB_WEAK
This page took 0.028416 seconds and 4 git commands to generate.