Fix problem where -relax could reorder multiple consecutive sets of the
[deliverable/binutils-gdb.git] / bfd / elf.c
index b4328c588fda113e7b8d9acd4ed438995439d3ac..436f8db9337d32d373864fc80ebfa29ff7e0777b 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1,5 +1,5 @@
 /* ELF executable support for BFD.
-   Copyright 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
+   Copyright 1993, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
 
 This file is part of BFD, the Binary File Descriptor library.
 
@@ -53,6 +53,7 @@ static boolean assign_section_numbers PARAMS ((bfd *));
 static INLINE int sym_is_global PARAMS ((bfd *, asymbol *));
 static boolean elf_map_symbols PARAMS ((bfd *));
 static bfd_size_type get_program_header_size PARAMS ((bfd *));
+static boolean elfcore_read_notes PARAMS ((bfd *, bfd_vma, bfd_vma));
 
 /* Swap version information in and out.  The version information is
    currently size independent.  If that ever changes, this code will
@@ -200,10 +201,12 @@ _bfd_elf_swap_versym_out (abfd, src, dst)
 
 /* Standard ELF hash function.  Do not change this function; you will
    cause invalid hash tables to be generated.  */
+
 unsigned long
-bfd_elf_hash (name)
-     CONST unsigned char *name;
+bfd_elf_hash (namearg)
+     const char *namearg;
 {
+  const unsigned char *name = (const unsigned char *) namearg;
   unsigned long h = 0;
   unsigned long g;
   int ch;
@@ -503,13 +506,13 @@ bfd_elf_generic_reloc (abfd,
                       input_section,
                       output_bfd,
                       error_message)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      arelent *reloc_entry;
      asymbol *symbol;
-     PTR data;
+     PTR data ATTRIBUTE_UNUSED;
      asection *input_section;
      bfd *output_bfd;
-     char **error_message;
+     char **error_message ATTRIBUTE_UNUSED;
 {
   if (output_bfd != (bfd *) NULL
       && (symbol->flags & BSF_SECTION_SYM) == 0
@@ -756,8 +759,22 @@ bfd_elf_print_symbol (abfd, filep, symbol, how)
     case bfd_print_symbol_all:
       {
        CONST char *section_name;
+       CONST char *name = NULL;
+       struct elf_backend_data *bed;
+       unsigned char st_other;
+       
        section_name = symbol->section ? symbol->section->name : "(*none*)";
-       bfd_print_symbol_vandf ((PTR) file, symbol);
+
+       bed = get_elf_backend_data (abfd);
+       if (bed->elf_backend_print_symbol_all)
+           name = (*bed->elf_backend_print_symbol_all) (abfd, filep, symbol);
+
+       if (name == NULL)
+         {
+           name = symbol->name;  
+           bfd_print_symbol_vandf ((PTR) file, symbol);
+         }
+
        fprintf (file, " %s\t", section_name);
        /* Print the "other" value for a symbol.  For common symbols,
           we've already printed the size; now print the alignment.
@@ -820,12 +837,21 @@ bfd_elf_print_symbol (abfd, filep, symbol, how)
          }
 
        /* If the st_other field is not zero, print it.  */
-       if (((elf_symbol_type *) symbol)->internal_elf_sym.st_other != 0)
-         fprintf (file, " 0x%02x",
-                  ((unsigned int)
-                   ((elf_symbol_type *) symbol)->internal_elf_sym.st_other));
+       st_other = ((elf_symbol_type *) symbol)->internal_elf_sym.st_other;
+       
+       switch (st_other)
+         {
+         case 0: break;
+         case STV_INTERNAL:  fprintf (file, " .internal");  break;
+         case STV_HIDDEN:    fprintf (file, " .hidden");    break;
+         case STV_PROTECTED: fprintf (file, " .protected"); break;
+         default:
+           /* Some other non-defined flags are also present, so print
+              everything hex.  */
+           fprintf (file, " 0x%02x", (unsigned int) st_other);
+         }
 
-       fprintf (file, " %s", symbol->name);
+       fprintf (file, " %s", name);
       }
       break;
     }
@@ -866,6 +892,7 @@ _bfd_elf_link_hash_newfunc (entry, table, string)
       ret->linker_section_pointer = (elf_linker_section_pointers_t *)0;
       ret->verinfo.verdef = NULL;
       ret->vtable_entries_used = NULL;
+      ret->vtable_entries_size = 0;
       ret->vtable_parent = NULL;
       ret->type = STT_NOTYPE;
       ret->other = 0;
@@ -943,7 +970,7 @@ bfd_elf_set_dt_needed_name (abfd, name)
 
 struct bfd_link_needed_list *
 bfd_elf_get_needed_list (abfd, info)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      struct bfd_link_info *info;
 {
   if (info->hash->creator->flavour != bfd_target_elf_flavour)
@@ -1200,6 +1227,15 @@ bfd_section_from_shdr (abfd, shindex)
        asection *target_sect;
        Elf_Internal_Shdr *hdr2;
 
+       /* Check for a bogus link to avoid crashing.  */
+       if (hdr->sh_link >= ehdr->e_shnum)
+         {
+           ((*_bfd_error_handler)
+            (_("%s: invalid link %lu for reloc section %s (index %u)"),
+             bfd_get_filename (abfd), hdr->sh_link, name, shindex));
+           return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+         }
+
        /* For some incomprehensible reason Oracle distributes
           libraries for Solaris in which some of the objects have
           bogus sh_link fields.  It would be nice if we could just
@@ -1264,6 +1300,10 @@ bfd_section_from_shdr (abfd, shindex)
        target_sect->flags |= SEC_RELOC;
        target_sect->relocation = NULL;
        target_sect->rel_filepos = hdr->sh_offset;
+       /* In the section to which the relocations apply, mark whether
+          its relocations are of the REL or RELA variety.  */
+       elf_section_data (target_sect)->use_rela_p 
+         = (hdr->sh_type == SHT_RELA);
        abfd->flags |= HAS_RELOC;
        return true;
       }
@@ -1323,11 +1363,15 @@ _bfd_elf_new_section_hook (abfd, sec)
 {
   struct bfd_elf_section_data *sdata;
 
-  sdata = (struct bfd_elf_section_data *) bfd_alloc (abfd, sizeof (*sdata));
+  sdata = (struct bfd_elf_section_data *) bfd_zalloc (abfd, sizeof (*sdata));
   if (!sdata)
     return false;
   sec->used_by_bfd = (PTR) sdata;
-  memset (sdata, 0, sizeof (*sdata));
+
+  /* Indicate whether or not this section should use RELA relocations.  */
+  sdata->use_rela_p 
+    = get_elf_backend_data (abfd)->default_use_rela_p;
+
   return true;
 }
 
@@ -1354,10 +1398,11 @@ _bfd_elf_new_section_hook (abfd, sec)
  */
 
 boolean
-bfd_section_from_phdr (abfd, hdr, index)
+_bfd_elf_make_section_from_phdr (abfd, hdr, index, typename)
      bfd *abfd;
      Elf_Internal_Phdr *hdr;
      int index;
+     const char *typename;
 {
   asection *newsect;
   char *name;
@@ -1367,7 +1412,7 @@ bfd_section_from_phdr (abfd, hdr, index)
   split = ((hdr->p_memsz > 0)
            && (hdr->p_filesz > 0)
            && (hdr->p_memsz > hdr->p_filesz));
-  sprintf (namebuf, split ? "segment%da" : "segment%d", index);
+  sprintf (namebuf, "%s%d%s", typename, index, split ? "a" : "");
   name = bfd_alloc (abfd, strlen (namebuf) + 1);
   if (!name)
     return false;
@@ -1398,7 +1443,7 @@ bfd_section_from_phdr (abfd, hdr, index)
 
   if (split)
     {
-      sprintf (namebuf, "segment%db", index);
+      sprintf (namebuf, "%s%db", typename, index);
       name = bfd_alloc (abfd, strlen (namebuf) + 1);
       if (!name)
        return false;
@@ -1422,6 +1467,89 @@ bfd_section_from_phdr (abfd, hdr, index)
   return true;
 }
 
+boolean
+bfd_section_from_phdr (abfd, hdr, index)
+     bfd *abfd;
+     Elf_Internal_Phdr *hdr;
+     int index;
+{
+  struct elf_backend_data *bed;
+
+  switch (hdr->p_type)
+    {
+    case PT_NULL:
+      return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "null");
+
+    case PT_LOAD:
+      return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "load");
+
+    case PT_DYNAMIC:
+      return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "dynamic");
+
+    case PT_INTERP:
+      return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "interp");
+
+    case PT_NOTE:
+      if (! _bfd_elf_make_section_from_phdr (abfd, hdr, index, "note"))
+       return false;
+      if (! elfcore_read_notes (abfd, hdr->p_offset, hdr->p_filesz))
+       return false;
+      return true;
+
+    case PT_SHLIB:
+      return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "shlib");
+
+    case PT_PHDR:
+      return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "phdr");
+
+    default:
+      /* Check for any processor-specific program segment types.
+         If no handler for them, default to making "segment" sections. */
+      bed = get_elf_backend_data (abfd);
+      if (bed->elf_backend_section_from_phdr)
+       return (*bed->elf_backend_section_from_phdr) (abfd, hdr, index);
+      else
+       return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "segment");
+    }
+}
+
+/* Initialize REL_HDR, the section-header for new section, containing
+   relocations against ASECT.  If USE_RELA_P is true, we use RELA
+   relocations; otherwise, we use REL relocations.  */
+
+boolean
+_bfd_elf_init_reloc_shdr (abfd, rel_hdr, asect, use_rela_p)
+     bfd *abfd;
+     Elf_Internal_Shdr *rel_hdr;
+     asection *asect;
+     boolean use_rela_p;
+{
+  char *name;
+  struct elf_backend_data *bed;
+
+  bed = get_elf_backend_data (abfd);
+  name = bfd_alloc (abfd, sizeof ".rela" + strlen (asect->name));
+  if (name == NULL)
+    return false;
+  sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", asect->name);
+  rel_hdr->sh_name =
+    (unsigned int) _bfd_stringtab_add (elf_shstrtab (abfd), name,
+                                      true, false);
+  if (rel_hdr->sh_name == (unsigned int) -1)
+    return false;
+  rel_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL;
+  rel_hdr->sh_entsize = (use_rela_p
+                        ? bed->s->sizeof_rela
+                        : bed->s->sizeof_rel);
+  rel_hdr->sh_addralign = bed->s->file_align;
+  rel_hdr->sh_flags = 0;
+  rel_hdr->sh_addr = 0;
+  rel_hdr->sh_size = 0;
+  rel_hdr->sh_offset = 0;
+
+  return true;
+}
+
 /* Set up an ELF internal section header for a section.  */
 
 /*ARGSUSED*/
@@ -1477,7 +1605,7 @@ elf_fake_sections (abfd, asect, failedptrarg)
   else if (strcmp (asect->name, ".hash") == 0)
     {
       this_hdr->sh_type = SHT_HASH;
-      this_hdr->sh_entsize = bed->s->arch_size / 8;
+      this_hdr->sh_entsize = bed->s->sizeof_hash_entry;
     }
   else if (strcmp (asect->name, ".dynsym") == 0)
     {
@@ -1490,13 +1618,13 @@ elf_fake_sections (abfd, asect, failedptrarg)
       this_hdr->sh_entsize = bed->s->sizeof_dyn;
     }
   else if (strncmp (asect->name, ".rela", 5) == 0
-          && get_elf_backend_data (abfd)->use_rela_p)
+          && get_elf_backend_data (abfd)->may_use_rela_p)
     {
       this_hdr->sh_type = SHT_RELA;
       this_hdr->sh_entsize = bed->s->sizeof_rela;
     }
   else if (strncmp (asect->name, ".rel", 4) == 0
-          && ! get_elf_backend_data (abfd)->use_rela_p)
+          && get_elf_backend_data (abfd)->may_use_rel_p)
     {
       this_hdr->sh_type = SHT_REL;
       this_hdr->sh_entsize = bed->s->sizeof_rel;
@@ -1557,47 +1685,19 @@ elf_fake_sections (abfd, asect, failedptrarg)
     this_hdr->sh_flags |= SHF_EXECINSTR;
 
   /* Check for processor-specific section types.  */
-  {
-    struct elf_backend_data *bed = get_elf_backend_data (abfd);
-
-    if (bed->elf_backend_fake_sections)
-      (*bed->elf_backend_fake_sections) (abfd, this_hdr, asect);
-  }
+  if (bed->elf_backend_fake_sections)
+    (*bed->elf_backend_fake_sections) (abfd, this_hdr, asect);
 
   /* If the section has relocs, set up a section header for the
-     SHT_REL[A] section.  */
-  if ((asect->flags & SEC_RELOC) != 0)
-    {
-      Elf_Internal_Shdr *rela_hdr;
-      int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
-      char *name;
-
-      rela_hdr = &elf_section_data (asect)->rel_hdr;
-      name = bfd_alloc (abfd, sizeof ".rela" + strlen (asect->name));
-      if (name == NULL)
-       {
-         *failedptr = true;
-         return;
-       }
-      sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", asect->name);
-      rela_hdr->sh_name =
-       (unsigned int) _bfd_stringtab_add (elf_shstrtab (abfd), name,
-                                          true, false);
-      if (rela_hdr->sh_name == (unsigned int) -1)
-       {
-         *failedptr = true;
-         return;
-       }
-      rela_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL;
-      rela_hdr->sh_entsize = (use_rela_p
-                             ? bed->s->sizeof_rela
-                             : bed->s->sizeof_rel);
-      rela_hdr->sh_addralign = bed->s->file_align;
-      rela_hdr->sh_flags = 0;
-      rela_hdr->sh_addr = 0;
-      rela_hdr->sh_size = 0;
-      rela_hdr->sh_offset = 0;
-    }
+     SHT_REL[A] section.  If two relocation sections are required for
+     this section, it is up to the processor-specific back-end to
+     create the other.  */ 
+  if ((asect->flags & SEC_RELOC) != 0
+      && !_bfd_elf_init_reloc_shdr (abfd, 
+                                   &elf_section_data (asect)->rel_hdr,
+                                   asect, 
+                                   elf_section_data (asect)->use_rela_p))
+    *failedptr = true;
 }
 
 /* Assign all ELF section numbers.  The dummy first section is handled here
@@ -1625,13 +1725,18 @@ assign_section_numbers (abfd)
        d->rel_idx = 0;
       else
        d->rel_idx = section_number++;
+
+      if (d->rel_hdr2)
+       d->rel_idx2 = section_number++;
+      else
+       d->rel_idx2 = 0;
     }
 
   t->shstrtab_section = section_number++;
   elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section;
   t->shstrtab_hdr.sh_size = _bfd_stringtab_size (elf_shstrtab (abfd));
 
-  if (abfd->symcount > 0)
+  if (bfd_get_symcount (abfd) > 0)
     {
       t->symtab_section = section_number++;
       t->strtab_section = section_number++;
@@ -1658,7 +1763,7 @@ assign_section_numbers (abfd)
   elf_elfsections (abfd) = i_shdrp;
 
   i_shdrp[t->shstrtab_section] = &t->shstrtab_hdr;
-  if (abfd->symcount > 0)
+  if (bfd_get_symcount (abfd) > 0)
     {
       i_shdrp[t->symtab_section] = &t->symtab_hdr;
       i_shdrp[t->strtab_section] = &t->strtab_hdr;
@@ -1673,6 +1778,8 @@ assign_section_numbers (abfd)
       i_shdrp[d->this_idx] = &d->this_hdr;
       if (d->rel_idx != 0)
        i_shdrp[d->rel_idx] = &d->rel_hdr;
+      if (d->rel_idx2 != 0)
+       i_shdrp[d->rel_idx2] = d->rel_hdr2;
 
       /* Fill in the sh_link and sh_info fields while we're at it.  */
 
@@ -1684,6 +1791,11 @@ assign_section_numbers (abfd)
          d->rel_hdr.sh_link = t->symtab_section;
          d->rel_hdr.sh_info = d->this_idx;
        }
+      if (d->rel_idx2 != 0)
+       {
+         d->rel_hdr2->sh_link = t->symtab_section;
+         d->rel_hdr2->sh_info = d->this_idx;
+       }
 
       switch (d->this_hdr.sh_type)
        {
@@ -1800,6 +1912,7 @@ elf_map_symbols (abfd)
   int idx;
   asection *asect;
   asymbol **new_syms;
+  asymbol *sym;
 
 #ifdef DEBUG
   fprintf (stderr, "elf_map_symbols\n");
@@ -1822,19 +1935,36 @@ elf_map_symbols (abfd)
 
   for (idx = 0; idx < symcount; idx++)
     {
-      if ((syms[idx]->flags & BSF_SECTION_SYM) != 0
-         && syms[idx]->value == 0)
+      sym = syms[idx];
+      
+      if ((sym->flags & BSF_SECTION_SYM) != 0
+         && sym->value == 0)
        {
          asection *sec;
 
-         sec = syms[idx]->section;
+         sec = sym->section;
+
          if (sec->owner != NULL)
            {
              if (sec->owner != abfd)
                {
                  if (sec->output_offset != 0)
                    continue;
+                 
                  sec = sec->output_section;
+
+                 /* Empty sections in the input files may have had a section
+                    symbol created for them.  (See the comment near the end of
+                    _bfd_generic_link_output_symbols in linker.c).  If the linker
+                    script discards such sections then we will reach this point.
+                    Since we know that we cannot avoid this case, we detect it
+                    and skip the abort and the assignment to the sect_syms array.
+                    To reproduce this particular case try running the linker
+                    testsuite test ld-scripts/weak.exp for an ELF port that uses
+                    the generic linker.  */
+                 if (sec->owner == NULL)
+                   continue;
+
                  BFD_ASSERT (sec->owner == abfd);
                }
              sect_syms[sec->index] = syms[idx];
@@ -1844,8 +1974,6 @@ elf_map_symbols (abfd)
 
   for (asect = abfd->sections; asect; asect = asect->next)
     {
-      asymbol *sym;
-
       if (sect_syms[asect->index] != NULL)
        continue;
 
@@ -1994,6 +2122,10 @@ _bfd_elf_compute_section_file_positions (abfd, link_info)
   if (! prep_headers (abfd))
     return false;
 
+  /* Post process the headers if necessary.  */
+  if (bed->elf_backend_post_process_headers)
+    (*bed->elf_backend_post_process_headers) (abfd, link_info);
+
   failed = false;
   bfd_map_over_sections (abfd, elf_fake_sections, &failed);
   if (failed)
@@ -2003,7 +2135,7 @@ _bfd_elf_compute_section_file_positions (abfd, link_info)
     return false;
 
   /* The backend linker builds symbol table information itself.  */
-  if (link_info == NULL && abfd->symcount > 0)
+  if (link_info == NULL && bfd_get_symcount (abfd) > 0)
     {
       /* Non-zero if doing a relocatable link.  */
       int relocatable_p = ! (abfd->flags & (EXEC_P | DYNAMIC));
@@ -2027,7 +2159,7 @@ _bfd_elf_compute_section_file_positions (abfd, link_info)
   if (!assign_file_positions_except_relocs (abfd))
     return false;
 
-  if (link_info == NULL && abfd->symcount > 0)
+  if (link_info == NULL && bfd_get_symcount (abfd) > 0)
     {
       file_ptr off;
       Elf_Internal_Shdr *hdr;
@@ -2497,11 +2629,7 @@ assign_file_positions_for_segments (abfd)
               elf_sort_sections);
 
       p->p_type = m->p_type;
-
-      if (m->p_flags_valid)
-       p->p_flags = m->p_flags;
-      else
-       p->p_flags = 0;
+      p->p_flags = m->p_flags;
 
       if (p->p_type == PT_LOAD
          && m->count > 0
@@ -2510,8 +2638,21 @@ assign_file_positions_for_segments (abfd)
          if ((abfd->flags & D_PAGED) != 0)
            off += (m->sections[0]->vma - off) % bed->maxpagesize;
          else
-           off += ((m->sections[0]->vma - off)
-                   % (1 << bfd_get_section_alignment (abfd, m->sections[0])));
+           {
+             bfd_size_type align;
+
+             align = 0;
+             for (i = 0, secpp = m->sections; i < m->count; i++, secpp++)
+               {
+                 bfd_size_type secalign;
+
+                 secalign = bfd_get_section_alignment (abfd, *secpp);
+                 if (secalign > align)
+                   align = secalign;
+               }
+
+             off += (m->sections[0]->vma - off) % (1 << align);
+           }
        }
 
       if (m->count == 0)
@@ -2607,7 +2748,7 @@ assign_file_positions_for_segments (abfd)
        }
 
       if (p->p_type == PT_LOAD
-         || (p->p_type == PT_NOTE && abfd->format == bfd_core))
+         || (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core))
        {
          if (! m->includes_filehdr && ! m->includes_phdrs)
            p->p_offset = off;
@@ -2706,7 +2847,7 @@ assign_file_positions_for_segments (abfd)
                voff += sec->_raw_size;
            }
 
-         if (p->p_type == PT_NOTE && abfd->format == bfd_core)
+         if (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core)
            {
              if (i == 0)       /* the actual "note" segment */
                {               /* this one actually contains everything. */
@@ -2731,7 +2872,8 @@ assign_file_positions_for_segments (abfd)
              if ((flags & SEC_LOAD) != 0)
                p->p_filesz += sec->_raw_size;
 
-             if (align > p->p_align)
+             if (align > p->p_align
+                 && (p->p_type != PT_LOAD || (abfd->flags & D_PAGED) == 0))
                p->p_align = align;
            }
 
@@ -2894,7 +3036,7 @@ assign_file_positions_except_relocs (abfd)
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
-      && abfd->format != bfd_core)
+      && bfd_get_format (abfd) != bfd_core)
     {
       Elf_Internal_Shdr **hdrpp;
       unsigned int i;
@@ -3011,6 +3153,9 @@ prep_headers (abfd)
     bfd_big_endian (abfd) ? ELFDATA2MSB : ELFDATA2LSB;
   i_ehdrp->e_ident[EI_VERSION] = bed->s->ev_current;
 
+  i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_SYSV;
+  i_ehdrp->e_ident[EI_ABIVERSION] = 0;
+
   for (count = EI_PAD; count < EI_NIDENT; count++)
     i_ehdrp->e_ident[count] = 0;
 
@@ -3046,6 +3191,9 @@ prep_headers (abfd)
     case bfd_arch_i860:
       i_ehdrp->e_machine = EM_860;
       break;
+    case bfd_arch_i960:
+      i_ehdrp->e_machine = EM_960;
+      break;
     case bfd_arch_mips:        /* MIPS Rxxxx */
       i_ehdrp->e_machine = EM_MIPS;    /* only MIPS R3000 */
       break;
@@ -3070,6 +3218,9 @@ prep_headers (abfd)
     case bfd_arch_fr30:
       i_ehdrp->e_machine = EM_CYGNUS_FR30;
       break;
+    case bfd_arch_mcore:
+      i_ehdrp->e_machine = EM_MCORE;
+      break;
     case bfd_arch_v850:
       switch (bfd_get_mach (abfd))
        {
@@ -3092,6 +3243,9 @@ prep_headers (abfd)
     case bfd_arch_mn10300:
       i_ehdrp->e_machine = EM_CYGNUS_MN10300;
       break;
+    case bfd_arch_pj:
+      i_ehdrp->e_machine = EM_PJ;
+      break;
       /* also note that EM_M32, AT&T WE32100 is unknown to bfd */
     default:
       i_ehdrp->e_machine = EM_NONE;
@@ -3371,7 +3525,7 @@ copy_private_bfd_data (ibfd, obfd)
 
 #define IS_COREFILE_NOTE(p, s)                                          \
            (p->p_type == PT_NOTE                                       \
-            && ibfd->format == bfd_core                                \
+            && bfd_get_format (ibfd) == bfd_core                       \
             && s->vma == 0 && s->lma == 0                              \
             && (bfd_vma) s->filepos >= p->p_offset                     \
             && (bfd_vma) s->filepos + s->_raw_size                     \
@@ -3443,6 +3597,8 @@ copy_private_bfd_data (ibfd, obfd)
       m->includes_filehdr = (p->p_offset == 0
                             && p->p_filesz >= iehdr->e_ehsize);
 
+      m->includes_phdrs = 0;
+
       if (! phdr_included || p->p_type != PT_LOAD)
        {
          m->includes_phdrs =
@@ -3791,6 +3947,9 @@ _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
       || ihdr->sh_type == SHT_GNU_verdef)
     ohdr->sh_info = ihdr->sh_info;
 
+  elf_section_data (osec)->use_rela_p
+    = elf_section_data (isec)->use_rela_p;
+
   return true;
 }
 
@@ -4104,7 +4263,7 @@ _bfd_elf_get_dynamic_symtab_upper_bound (abfd)
 
 long
 _bfd_elf_get_reloc_upper_bound (abfd, asect)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      sec_ptr asect;
 {
   return (asect->reloc_count + 1) * sizeof (arelent *);
@@ -4435,7 +4594,7 @@ _bfd_elf_make_empty_symbol (abfd)
 
 void
 _bfd_elf_get_symbol_info (ignore_abfd, symbol, ret)
-     bfd *ignore_abfd;
+     bfd *ignore_abfd ATTRIBUTE_UNUSED;
      asymbol *symbol;
      symbol_info *ret;
 {
@@ -4448,7 +4607,7 @@ _bfd_elf_get_symbol_info (ignore_abfd, symbol, ret)
 
 boolean
 _bfd_elf_is_local_label_name (abfd, name)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      const char *name;
 {
   /* Normal local symbols start with ``.L''.  */
@@ -4474,8 +4633,8 @@ _bfd_elf_is_local_label_name (abfd, name)
 
 alent *
 _bfd_elf_get_lineno (ignore_abfd, symbol)
-     bfd *ignore_abfd;
-     asymbol *symbol;
+     bfd *ignore_abfd ATTRIBUTE_UNUSED;
+     asymbol *symbol ATTRIBUTE_UNUSED;
 {
   abort ();
   return NULL;
@@ -4529,7 +4688,7 @@ _bfd_elf_find_nearest_line (abfd,
 
   if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
                                     filename_ptr, functionname_ptr,
-                                    line_ptr))
+                                    line_ptr, 0))
     return true;
 
   if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
@@ -4625,9 +4784,9 @@ _bfd_elf_set_section_contents (abfd, section, location, offset, count)
 
 void
 _bfd_elf_no_info_to_howto (abfd, cache_ptr, dst)
-     bfd *abfd;
-     arelent *cache_ptr;
-     Elf_Internal_Rela *dst;
+     bfd *abfd ATTRIBUTE_UNUSED;
+     arelent *cache_ptr ATTRIBUTE_UNUSED;
+     Elf_Internal_Rela *dst ATTRIBUTE_UNUSED;
 {
   abort ();
 }
@@ -4761,13 +4920,13 @@ _bfd_elf_close_and_cleanup (abfd)
 
 bfd_reloc_status_type
 _bfd_elf_rel_vtable_reloc_fn (abfd, re, symbol, data, is, obfd, errmsg)
-     bfd *abfd;
-     arelent *re;
-     struct symbol_cache_entry *symbol;
-     PTR data;
-     asection *is;
-     bfd *obfd;
-     char **errmsg;
+     bfd *abfd ATTRIBUTE_UNUSED;
+     arelent *re ATTRIBUTE_UNUSED;
+     struct symbol_cache_entry *symbol ATTRIBUTE_UNUSED;
+     PTR data ATTRIBUTE_UNUSED;
+     asection *is ATTRIBUTE_UNUSED;
+     bfd *obfd ATTRIBUTE_UNUSED;
+     char **errmsg ATTRIBUTE_UNUSED;
 {
   return bfd_reloc_ok;
 }
@@ -4888,28 +5047,33 @@ elfcore_grok_prstatus (abfd, note)
 #endif /* defined (HAVE_PRSTATUS_T) */
 
 
-/* There isn't a consistent prfpregset_t across platforms,
-   but it doesn't matter, because we don't have to pick this
-   data structure apart. */
+/* Create a pseudosection containing the exact contents of NOTE.  This
+   actually creates up to two pseudosections:
+   - For the single-threaded case, a section named NAME, unless
+     such a section already exists.
+   - For the multi-threaded case, a section named "NAME/PID", where
+     PID is elfcore_make_pid (abfd).
+   Both pseudosections have identical contents: the contents of NOTE.  */
 
 static boolean
-elfcore_grok_prfpreg (abfd, note)
+elfcore_make_note_pseudosection (abfd, name, note)
      bfd* abfd;
+     char *name;
      Elf_Internal_Note* note;
 {
   char buf[100];
-  charname;
+  char *threaded_name;
   asection* sect;
 
-  /* Make a ".reg2/999" section. */
+  /* Build the section name.  */
 
-  sprintf (buf, ".reg2/%d", elfcore_make_pid (abfd));
-  name = bfd_alloc (abfd, strlen (buf) + 1);
-  if (name == NULL)
+  sprintf (buf, "%s/%d", name, elfcore_make_pid (abfd));
+  threaded_name = bfd_alloc (abfd, strlen (buf) + 1);
+  if (threaded_name == NULL)
     return false;
-  strcpy (name, buf);
+  strcpy (threaded_name, buf);
 
-  sect = bfd_make_section (abfd, name);
+  sect = bfd_make_section (abfd, threaded_name);
   if (sect == NULL)
     return false;
   sect->_raw_size = note->descsz;
@@ -4917,13 +5081,48 @@ elfcore_grok_prfpreg (abfd, note)
   sect->flags = SEC_HAS_CONTENTS;
   sect->alignment_power = 2;
 
-  if (! elfcore_maybe_make_sect (abfd, ".reg2", sect))
+  if (! elfcore_maybe_make_sect (abfd, name, sect))
     return false;
 
   return true;
 }
 
 
+/* There isn't a consistent prfpregset_t across platforms,
+   but it doesn't matter, because we don't have to pick this
+   data structure apart. */
+static boolean
+elfcore_grok_prfpreg (abfd, note)
+     bfd* abfd;
+     Elf_Internal_Note* note;
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg2", 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
+   literally.  */
+static boolean
+elfcore_grok_prxfpreg (abfd, note)
+     bfd* abfd;
+     Elf_Internal_Note* note;
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-xfp", note);
+}
+
+
+#if defined (HAVE_PRPSINFO_T)
+# define elfcore_psinfo_t prpsinfo_t
+#endif
+
+#if defined (HAVE_PSINFO_T)
+# define elfcore_psinfo_t psinfo_t
+#endif
+
+
+#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
+
 /* return a malloc'ed copy of a string at START which is at
    most MAX bytes long, possibly without a terminating '\0'.
    the copy will always have a terminating '\0'. */
@@ -4953,17 +5152,6 @@ elfcore_strndup (abfd, start, max)
   return dup;
 }
 
-
-#if defined (HAVE_PRPSINFO_T)
-# define elfcore_psinfo_t prpsinfo_t
-#endif
-
-#if defined (HAVE_PSINFO_T)
-# define elfcore_psinfo_t psinfo_t
-#endif
-
-
-#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
 static boolean
 elfcore_grok_psinfo (abfd, note)
      bfd* abfd;
@@ -5104,7 +5292,83 @@ elfcore_grok_lwpstatus (abfd, note)
 }
 #endif /* defined (HAVE_LWPSTATUS_T) */
 
+#if defined (HAVE_WIN32_PSTATUS_T)
+static boolean
+elfcore_grok_win32pstatus (abfd, note)
+     bfd * abfd;
+     Elf_Internal_Note * note;
+{
+  char buf[30];
+  char * name;
+  asection * sect;
+  win32_pstatus_t pstatus;
+
+  if (note->descsz < sizeof (pstatus))
+    return true;
 
+  memcpy (& pstatus, note->descdata, note->descsz);
+  
+  switch (pstatus.data_type) 
+    {
+    case NOTE_INFO_PROCESS:
+      /* FIXME: need to add ->core_command.  */
+      elf_tdata (abfd)->core_signal = pstatus.data.process_info.signal;
+      elf_tdata (abfd)->core_pid = pstatus.data.process_info.pid;
+      break ;
+
+    case NOTE_INFO_THREAD:
+      /* Make a ".reg/999" section.  */
+      sprintf (buf, ".reg/%d", pstatus.data.thread_info.tid);
+      
+      name = bfd_alloc (abfd, strlen (buf) + 1);
+      if (name == NULL)
+        return false;
+      
+      strcpy (name, buf);
+
+      sect = bfd_make_section (abfd, name);
+      if (sect == NULL)
+        return false;
+      
+      sect->_raw_size = sizeof (pstatus.data.thread_info.thread_context);
+      sect->filepos = note->descpos + offsetof (struct win32_pstatus,
+                                               data.thread_info.thread_context);
+      sect->flags = SEC_HAS_CONTENTS;
+      sect->alignment_power = 2;
+
+      if (pstatus.data.thread_info.is_active_thread)
+       if (! elfcore_maybe_make_sect (abfd, ".reg", sect))
+         return false;
+      break;
+
+    case NOTE_INFO_MODULE:
+      /* Make a ".module/xxxxxxxx" section.  */
+      sprintf (buf, ".module/%08x" , pstatus.data.module_info.base_address);
+      
+      name = bfd_alloc (abfd, strlen (buf) + 1);
+      if (name == NULL)
+       return false;
+      
+      strcpy (name, buf);
+
+      sect = bfd_make_section (abfd, name);
+      
+      if (sect == NULL)
+       return false;
+      
+      sect->_raw_size = note->descsz;
+      sect->filepos = note->descpos;
+      sect->flags = SEC_HAS_CONTENTS;
+      sect->alignment_power = 2;
+      break;
+
+    default:
+      return true;
+    }
+
+  return true;
+}
+#endif /* HAVE_WIN32_PSTATUS_T */
 
 static boolean
 elfcore_grok_note (abfd, note)
@@ -5134,6 +5398,18 @@ elfcore_grok_note (abfd, note)
     case NT_FPREGSET:          /* FIXME: rename to NT_PRFPREG */
       return elfcore_grok_prfpreg (abfd, note);
 
+#if defined (HAVE_WIN32_PSTATUS_T)
+    case NT_WIN32PSTATUS:      
+      return elfcore_grok_win32pstatus (abfd, note);
+#endif
+
+  case NT_PRXFPREG:            /* Linux SSE extension */
+      if (note->namesz == 5
+         && ! strcmp (note->namedata, "LINUX"))
+       return elfcore_grok_prxfpreg (abfd, note);
+      else
+       return true;
+
 #if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
     case NT_PRPSINFO:
     case NT_PSINFO:
@@ -5196,6 +5472,8 @@ elfcore_read_notes (abfd, offset, size)
 }
 
 
+/* FIXME: This function is now unnecessary.  Callers can just call
+   bfd_section_from_phdr directly.  */
 
 boolean
 _bfd_elfcore_section_from_phdr (abfd, phdr, sec_num)
@@ -5206,10 +5484,54 @@ _bfd_elfcore_section_from_phdr (abfd, phdr, sec_num)
   if (! bfd_section_from_phdr (abfd, phdr, sec_num))
     return false;
 
-  if (phdr->p_type == PT_NOTE
-      && ! elfcore_read_notes (abfd, phdr->p_offset, phdr->p_filesz))
-    return false;
-
   return true;
 }
 
+
+\f
+/* Providing external access to the ELF program header table.  */
+
+/* Return an upper bound on the number of bytes required to store a
+   copy of ABFD's program header table entries.  Return -1 if an error
+   occurs; bfd_get_error will return an appropriate code.  */
+long
+bfd_get_elf_phdr_upper_bound (abfd)
+     bfd *abfd;
+{
+  if (abfd->xvec->flavour != bfd_target_elf_flavour)
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return -1;
+    }
+
+  return (elf_elfheader (abfd)->e_phnum
+         * sizeof (Elf_Internal_Phdr));
+}
+
+
+/* Copy ABFD's program header table entries to *PHDRS.  The entries
+   will be stored as an array of Elf_Internal_Phdr structures, as
+   defined in include/elf/internal.h.  To find out how large the
+   buffer needs to be, call bfd_get_elf_phdr_upper_bound.
+
+   Return the number of program header table entries read, or -1 if an
+   error occurs; bfd_get_error will return an appropriate code.  */
+int
+bfd_get_elf_phdrs (abfd, phdrs)
+     bfd *abfd;
+     void *phdrs;
+{
+  int num_phdrs;
+
+  if (abfd->xvec->flavour != bfd_target_elf_flavour)
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return -1;
+    }
+
+  num_phdrs = elf_elfheader (abfd)->e_phnum;
+  memcpy (phdrs, elf_tdata (abfd)->phdr, 
+         num_phdrs * sizeof (Elf_Internal_Phdr));
+
+  return num_phdrs;
+}
This page took 0.035982 seconds and 4 git commands to generate.