daily update
[deliverable/binutils-gdb.git] / bfd / elf.c
index 966ada024b1a238b2aba4c029dc135c1b4a75f33..5aabeeb1cdc416cb17432a8d734bb2a788187264 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, 2008, 2009, 2010, 2011
+   2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
    Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -976,7 +976,9 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
       phdr = elf_tdata (abfd)->phdr;
       for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
        {
-         if (phdr->p_type == PT_LOAD
+         if (((phdr->p_type == PT_LOAD
+               && (hdr->sh_flags & SHF_TLS) == 0)
+              || phdr->p_type == PT_TLS)
              && ELF_SECTION_IN_SEGMENT (hdr, phdr))
            {
              if ((flags & SEC_LOAD) == 0)
@@ -3987,8 +3989,12 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
          phdr_in_segment = FALSE;
        }
 
-      /* Create a final PT_LOAD program segment.  */
-      if (last_hdr != NULL)
+      /* Create a final PT_LOAD program segment, but not if it's just
+        for .tbss.  */
+      if (last_hdr != NULL
+         && (i - phdr_index != 1
+             || ((last_hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD))
+                 != SEC_THREAD_LOCAL)))
        {
          m = make_mapping (abfd, sections, phdr_index, i, phdr_in_segment);
          if (m == NULL)
@@ -4684,6 +4690,21 @@ assign_file_positions_for_load_sections (bfd *abfd,
                  if (this_hdr->sh_type != SHT_NOBITS)
                    off += this_hdr->sh_size;
                }
+             else if (this_hdr->sh_type == SHT_NOBITS
+                      && (this_hdr->sh_flags & SHF_TLS) != 0
+                      && this_hdr->sh_offset == 0)
+               {
+                 /* This is a .tbss section that didn't get a PT_LOAD.
+                    (See _bfd_elf_map_sections_to_segments "Create a
+                    final PT_LOAD".)  Set sh_offset to the value it
+                    would have if we had created a zero p_filesz and
+                    p_memsz PT_LOAD header for the section.  This
+                    also makes the PT_TLS header have the same
+                    p_offset value.  */
+                 bfd_vma adjust = vma_page_aligned_bias (this_hdr->sh_addr,
+                                                         off, align);
+                 this_hdr->sh_offset = sec->filepos = off + adjust;
+               }
 
              if (this_hdr->sh_type != SHT_NOBITS)
                {
@@ -4748,7 +4769,8 @@ assign_file_positions_for_load_sections (bfd *abfd,
 
              sec = m->sections[i];
              this_hdr = &(elf_section_data(sec)->this_hdr);
-             if (!ELF_SECTION_IN_SEGMENT_1 (this_hdr, p, check_vma, 0))
+             if (!ELF_SECTION_IN_SEGMENT_1 (this_hdr, p, check_vma, 0)
+                 && !ELF_TBSS_SPECIAL (this_hdr, p))
                {
                  (*_bfd_error_handler)
                    (_("%B: section `%A' can't be allocated in segment %d"),
@@ -4919,17 +4941,21 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
              && (p->p_type != PT_NOTE
                  || bfd_get_format (abfd) != bfd_core))
            {
-             Elf_Internal_Shdr *hdr;
-             asection *sect;
-
              BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs);
 
-             sect = m->sections[m->count - 1];
-             hdr = &elf_section_data (sect)->this_hdr;
-             p->p_filesz = sect->filepos - m->sections[0]->filepos;
-             if (hdr->sh_type != SHT_NOBITS)
-               p->p_filesz += hdr->sh_size;
+             p->p_filesz = 0;
              p->p_offset = m->sections[0]->filepos;
+             for (i = m->count; i-- != 0;)
+               {
+                 asection *sect = m->sections[i];
+                 Elf_Internal_Shdr *hdr = &elf_section_data (sect)->this_hdr;
+                 if (hdr->sh_type != SHT_NOBITS)
+                   {
+                     p->p_filesz = (sect->filepos - m->sections[0]->filepos
+                                    + hdr->sh_size);
+                     break;
+                   }
+               }
            }
        }
       else if (m->includes_filehdr)
@@ -6248,6 +6274,8 @@ _bfd_elf_init_private_section_data (bfd *ibfd,
       || obfd->xvec->flavour != bfd_target_elf_flavour)
     return TRUE;
 
+  BFD_ASSERT (elf_section_data (osec) != NULL);
+
   /* For objcopy and relocatable link, don't copy the output ELF
      section type from input if the output BFD section flags have been
      set to something different.  For a final link allow some flags
@@ -7365,6 +7393,9 @@ elf_find_function (bfd *abfd,
   enum { nothing_seen, symbol_seen, file_after_symbol_seen } state;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
+  if (symbols == NULL)
+    return FALSE;
+
   filename = NULL;
   func = NULL;
   file = NULL;
@@ -7373,36 +7404,30 @@ elf_find_function (bfd *abfd,
 
   for (p = symbols; *p != NULL; p++)
     {
-      elf_symbol_type *q;
-      unsigned int type;
+      asymbol *sym = *p;
+      asection *code_sec;
+      bfd_vma code_off;
 
-      q = (elf_symbol_type *) *p;
-
-      type = ELF_ST_TYPE (q->internal_elf_sym.st_info);
-      switch (type)
+      if ((sym->flags & BSF_FILE) != 0)
        {
-       case STT_FILE:
-         file = &q->symbol;
+         file = sym;
          if (state == symbol_seen)
            state = file_after_symbol_seen;
          continue;
-       default:
-         if (!bed->is_function_type (type))
-           break;
-       case STT_NOTYPE:
-         if (bfd_get_section (&q->symbol) == section
-             && q->symbol.value >= low_func
-             && q->symbol.value <= offset)
-           {
-             func = (asymbol *) q;
-             low_func = q->symbol.value;
-             filename = NULL;
-             if (file != NULL
-                 && (ELF_ST_BIND (q->internal_elf_sym.st_info) == STB_LOCAL
-                     || state != file_after_symbol_seen))
-               filename = bfd_asymbol_name (file);
-           }
-         break;
+       }
+
+      if (bed->maybe_function_sym (sym, &code_sec, &code_off)
+         && code_sec == section
+         && code_off >= low_func
+         && code_off <= offset)
+       {
+         func = sym;
+         low_func = code_off;
+         filename = NULL;
+         if (file != NULL
+             && ((sym->flags & BSF_LOCAL) != 0
+                 || state != file_after_symbol_seen))
+           filename = bfd_asymbol_name (file);
        }
       if (state == nothing_seen)
        state = symbol_seen;
@@ -7445,7 +7470,8 @@ _bfd_elf_find_nearest_line (bfd *abfd,
       return TRUE;
     }
 
-  if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
+  if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections,
+                                     section, symbols, offset,
                                     filename_ptr, functionname_ptr,
                                     line_ptr, 0,
                                     &elf_tdata (abfd)->dwarf2_find_line_info))
@@ -7666,11 +7692,12 @@ _bfd_elf_validate_reloc (bfd *abfd, arelent *areloc)
 bfd_boolean
 _bfd_elf_close_and_cleanup (bfd *abfd)
 {
-  if (bfd_get_format (abfd) == bfd_object)
+  struct elf_obj_tdata *tdata = elf_tdata (abfd);
+  if (bfd_get_format (abfd) == bfd_object && tdata != NULL)
     {
-      if (elf_tdata (abfd) != NULL && elf_shstrtab (abfd) != NULL)
+      if (elf_shstrtab (abfd) != NULL)
        _bfd_elf_strtab_free (elf_shstrtab (abfd));
-      _bfd_dwarf2_cleanup_debug_info (abfd);
+      _bfd_dwarf2_cleanup_debug_info (abfd, &tdata->dwarf2_find_line_info);
     }
 
   return _bfd_generic_close_and_cleanup (abfd);
@@ -7950,6 +7977,24 @@ elfcore_grok_s390_prefix (bfd *abfd, Elf_Internal_Note *note)
   return elfcore_make_note_pseudosection (abfd, ".reg-s390-prefix", note);
 }
 
+static bfd_boolean
+elfcore_grok_s390_last_break (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-s390-last-break", note);
+}
+
+static bfd_boolean
+elfcore_grok_s390_system_call (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-s390-system-call", note);
+}
+
+static bfd_boolean
+elfcore_grok_arm_vfp (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-arm-vfp", note);
+}
+
 #if defined (HAVE_PRPSINFO_T)
 typedef prpsinfo_t   elfcore_psinfo_t;
 #if defined (HAVE_PRPSINFO32_T)                /* Sparc64 cross Sparc32 */
@@ -8000,7 +8045,9 @@ elfcore_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
 
       memcpy (&psinfo, note->descdata, sizeof (psinfo));
 
+#if defined (HAVE_PSINFO_T_PR_PID) || defined (HAVE_PRPSINFO_T_PR_PID)
       elf_tdata (abfd)->core_pid = psinfo.pr_pid;
+#endif
       elf_tdata (abfd)->core_program
        = _bfd_elfcore_strndup (abfd, psinfo.pr_fname,
                                sizeof (psinfo.pr_fname));
@@ -8017,7 +8064,9 @@ elfcore_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
 
       memcpy (&psinfo, note->descdata, sizeof (psinfo));
 
+#if defined (HAVE_PSINFO32_T_PR_PID) || defined (HAVE_PRPSINFO32_T_PR_PID)
       elf_tdata (abfd)->core_pid = psinfo.pr_pid;
+#endif
       elf_tdata (abfd)->core_program
        = _bfd_elfcore_strndup (abfd, psinfo.pr_fname,
                                sizeof (psinfo.pr_fname));
@@ -8365,6 +8414,27 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
       else
         return TRUE;
 
+    case NT_S390_LAST_BREAK:
+      if (note->namesz == 6
+          && strcmp (note->namedata, "LINUX") == 0)
+        return elfcore_grok_s390_last_break (abfd, note);
+      else
+        return TRUE;
+
+    case NT_S390_SYSTEM_CALL:
+      if (note->namesz == 6
+          && strcmp (note->namedata, "LINUX") == 0)
+        return elfcore_grok_s390_system_call (abfd, note);
+      else
+        return TRUE;
+
+    case NT_ARM_VFP:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_arm_vfp (abfd, note);
+      else
+       return TRUE;
+
     case NT_PRPSINFO:
     case NT_PSINFO:
       if (bed->elf_backend_grok_psinfo)
@@ -8814,7 +8884,6 @@ elfcore_write_note (bfd *abfd,
   return buf;
 }
 
-#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
 char *
 elfcore_write_prpsinfo (bfd  *abfd,
                        char *buf,
@@ -8822,7 +8891,6 @@ elfcore_write_prpsinfo (bfd  *abfd,
                        const char *fname,
                        const char *psargs)
 {
-  const char *note_name = "CORE";
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   if (bed->elf_backend_write_core_note != NULL)
@@ -8834,6 +8902,7 @@ elfcore_write_prpsinfo (bfd  *abfd,
        return ret;
     }
 
+#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
 #if defined (HAVE_PRPSINFO32_T) || defined (HAVE_PSINFO32_T)
   if (bed->s->elfclass == ELFCLASS32)
     {
@@ -8849,7 +8918,7 @@ elfcore_write_prpsinfo (bfd  *abfd,
       strncpy (data.pr_fname, fname, sizeof (data.pr_fname));
       strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs));
       return elfcore_write_note (abfd, buf, bufsiz,
-                                note_name, note_type, &data, sizeof (data));
+                                "CORE", note_type, &data, sizeof (data));
     }
   else
 #endif
@@ -8866,12 +8935,14 @@ elfcore_write_prpsinfo (bfd  *abfd,
       strncpy (data.pr_fname, fname, sizeof (data.pr_fname));
       strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs));
       return elfcore_write_note (abfd, buf, bufsiz,
-                                note_name, note_type, &data, sizeof (data));
+                                "CORE", note_type, &data, sizeof (data));
     }
-}
 #endif /* PSINFO_T or PRPSINFO_T */
 
-#if defined (HAVE_PRSTATUS_T)
+  free (buf);
+  return NULL;
+}
+
 char *
 elfcore_write_prstatus (bfd *abfd,
                        char *buf,
@@ -8880,7 +8951,6 @@ elfcore_write_prstatus (bfd *abfd,
                        int cursig,
                        const void *gregs)
 {
-  const char *note_name = "CORE";
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   if (bed->elf_backend_write_core_note != NULL)
@@ -8893,6 +8963,7 @@ elfcore_write_prstatus (bfd *abfd,
        return ret;
     }
 
+#if defined (HAVE_PRSTATUS_T)
 #if defined (HAVE_PRSTATUS32_T)
   if (bed->s->elfclass == ELFCLASS32)
     {
@@ -8902,7 +8973,7 @@ elfcore_write_prstatus (bfd *abfd,
       prstat.pr_pid = pid;
       prstat.pr_cursig = cursig;
       memcpy (&prstat.pr_reg, gregs, sizeof (prstat.pr_reg));
-      return elfcore_write_note (abfd, buf, bufsiz, note_name,
+      return elfcore_write_note (abfd, buf, bufsiz, "CORE",
                                 NT_PRSTATUS, &prstat, sizeof (prstat));
     }
   else
@@ -8914,12 +8985,15 @@ elfcore_write_prstatus (bfd *abfd,
       prstat.pr_pid = pid;
       prstat.pr_cursig = cursig;
       memcpy (&prstat.pr_reg, gregs, sizeof (prstat.pr_reg));
-      return elfcore_write_note (abfd, buf, bufsiz, note_name,
+      return elfcore_write_note (abfd, buf, bufsiz, "CORE",
                                 NT_PRSTATUS, &prstat, sizeof (prstat));
     }
-}
 #endif /* HAVE_PRSTATUS_T */
 
+  free (buf);
+  return NULL;
+}
+
 #if defined (HAVE_LWPSTATUS_T)
 char *
 elfcore_write_lwpstatus (bfd *abfd,
@@ -9118,6 +9192,44 @@ elfcore_write_s390_prefix (bfd *abfd,
                              note_name, NT_S390_PREFIX, s390_prefix, size);
 }
 
+char *
+elfcore_write_s390_last_break (bfd *abfd,
+                              char *buf,
+                              int *bufsiz,
+                              const void *s390_last_break,
+                              int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                             note_name, NT_S390_LAST_BREAK,
+                            s390_last_break, size);
+}
+
+char *
+elfcore_write_s390_system_call (bfd *abfd,
+                               char *buf,
+                               int *bufsiz,
+                               const void *s390_system_call,
+                               int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                             note_name, NT_S390_SYSTEM_CALL,
+                            s390_system_call, size);
+}
+
+char *
+elfcore_write_arm_vfp (bfd *abfd,
+                      char *buf,
+                      int *bufsiz,
+                      const void *arm_vfp,
+                      int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                            note_name, NT_ARM_VFP, arm_vfp, size);
+}
+
 char *
 elfcore_write_register_note (bfd *abfd,
                             char *buf,
@@ -9148,6 +9260,12 @@ elfcore_write_register_note (bfd *abfd,
     return elfcore_write_s390_ctrs (abfd, buf, bufsiz, data, size);
   if (strcmp (section, ".reg-s390-prefix") == 0)
     return elfcore_write_s390_prefix (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-s390-last-break") == 0)
+    return elfcore_write_s390_last_break (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-s390-system-call") == 0)
+    return elfcore_write_s390_system_call (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-arm-vfp") == 0)
+    return elfcore_write_arm_vfp (abfd, buf, bufsiz, data, size);
   return NULL;
 }
 
@@ -9548,11 +9666,11 @@ _bfd_elf_set_osabi (bfd * 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
+     osabi field to ELFOSABI_GNU if the binary contains symbols of
      the STT_GNU_IFUNC type or STB_GNU_UNIQUE binding.  */
   if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE
       && elf_tdata (abfd)->has_gnu_symbols)
-    i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_LINUX;
+    i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_GNU;
 }
 
 
@@ -9566,3 +9684,19 @@ _bfd_elf_is_function_type (unsigned int type)
   return (type == STT_FUNC
          || type == STT_GNU_IFUNC);
 }
+
+/* Return TRUE iff the ELF symbol SYM might be a function.  Set *CODE_SEC
+   and *CODE_OFF to the function's entry point.  */
+
+bfd_boolean
+_bfd_elf_maybe_function_sym (const asymbol *sym,
+                            asection **code_sec, bfd_vma *code_off)
+{
+  if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT
+                    | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0)
+    return FALSE;
+
+  *code_sec = sym->section;
+  *code_off = sym->value;
+  return TRUE;
+}
This page took 0.031352 seconds and 4 git commands to generate.