2001-12-19 Michael Snyder <msnyder@redhat.com>
[deliverable/binutils-gdb.git] / bfd / elf.c
index 16c6fcb17d8a68c85a3133b51d65cec9d43ac166..92b60071dc5987406b32255a30a8ebb56e216415 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -40,6 +40,7 @@ SECTION
 #include "libbfd.h"
 #define ARCH_SIZE 0
 #include "elf-bfd.h"
+#include "libiberty.h"
 
 static INLINE struct elf_segment_map *make_mapping
   PARAMS ((bfd *, asection **, unsigned int, unsigned int, boolean));
@@ -70,6 +71,11 @@ static boolean elfcore_grok_prfpreg PARAMS ((bfd *, Elf_Internal_Note *));
 static boolean elfcore_grok_prxfpreg PARAMS ((bfd *, Elf_Internal_Note *));
 static boolean elfcore_grok_note PARAMS ((bfd *, Elf_Internal_Note *));
 
+static boolean elfcore_netbsd_get_lwpid PARAMS ((Elf_Internal_Note *, int *));
+static boolean elfcore_grok_netbsd_procinfo PARAMS ((bfd *,
+                                                    Elf_Internal_Note *));
+static boolean elfcore_grok_netbsd_note PARAMS ((bfd *, Elf_Internal_Note *));
+
 /* Swap version information in and out.  The version information is
    currently size independent.  If that ever changes, this code will
    need to move into elfcode.h.  */
@@ -374,7 +380,7 @@ setup_group (abfd, hdr, newsect)
 
       /* First count the number of groups.  If we have a SHT_GROUP
         section with just a flag word (ie. sh_size is 4), ignore it.  */
-      shnum = elf_elfheader (abfd)->e_shnum;
+      shnum = elf_numsections (abfd);
       num_group = 0;
       for (i = 0; i < shnum; i++)
        {
@@ -466,7 +472,7 @@ setup_group (abfd, hdr, newsect)
          while (--n_elt != 0)
            if ((++idx)->shdr == hdr)
              {
-               asection *s;
+               asection *s = NULL;
 
                /* We are a member of this group.  Go looking through
                   other members to see if any others are linked via
@@ -599,7 +605,7 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
     };
     int i;
 
-    for (i = sizeof (debug_sec_names) / sizeof (debug_sec_names[0]); i--;)
+    for (i = ARRAY_SIZE (debug_sec_names); i--;)
       if (strncmp (name, debug_sec_names[i], strlen (debug_sec_names[i])) == 0)
        break;
 
@@ -643,17 +649,30 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
          phdr = elf_tdata (abfd)->phdr;
          for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
            {
+             /* This section is part of this segment if its file
+                offset plus size lies within the segment's memory
+                span and, if the section is loaded, the extent of the
+                loaded data lies within the extent of the segment.  
+                If the p_paddr field is not set, we don't alter the 
+                LMA.  */
              if (phdr->p_type == PT_LOAD
-                 && phdr->p_vaddr != phdr->p_paddr
-                 && phdr->p_vaddr <= hdr->sh_addr
-                 && (phdr->p_vaddr + phdr->p_memsz
-                     >= hdr->sh_addr + hdr->sh_size)
+                 && phdr->p_paddr
+                 && (bfd_vma) hdr->sh_offset >= phdr->p_offset
+                 && (hdr->sh_offset + hdr->sh_size
+                     <= phdr->p_offset + phdr->p_memsz)
                  && ((flags & SEC_LOAD) == 0
-                     || (phdr->p_offset <= (bfd_vma) hdr->sh_offset
-                         && (phdr->p_offset + phdr->p_filesz
-                             >= hdr->sh_offset + hdr->sh_size))))
+                     || (phdr->p_offset + phdr->p_filesz
+                         >= hdr->sh_offset + hdr->sh_size)))
                {
-                 newsect->lma += phdr->p_paddr - phdr->p_vaddr;
+                 /* We used to do a relative adjustment here, but
+                    that doesn't work if the segment is packed with
+                    code from multiple VMAs.  Instead we calculate
+                    the LMA absoultely, based on the LMA of the
+                    segment (it is assumed that the segment will
+                    contain sections with contiguous LMAs, even if
+                    the VMAs are not).  */
+                 newsect->lma = phdr->p_paddr
+                   + hdr->sh_offset - phdr->p_offset;
                  break;
                }
            }
@@ -694,11 +713,11 @@ bfd_elf_find_section (abfd, name)
   i_shdrp = elf_elfsections (abfd);
   if (i_shdrp != NULL)
     {
-      shstrtab = bfd_elf_get_str_section
-       (abfd, elf_elfheader (abfd)->e_shstrndx);
+      shstrtab = bfd_elf_get_str_section (abfd,
+                                         elf_elfheader (abfd)->e_shstrndx);
       if (shstrtab != NULL)
        {
-         max = elf_elfheader (abfd)->e_shnum;
+         max = elf_numsections (abfd);
          for (i = 1; i < max; i++)
            if (!strcmp (&shstrtab[i_shdrp[i]->sh_name], name))
              return i_shdrp[i];
@@ -765,6 +784,28 @@ _bfd_elf_merge_sections (abfd, info)
   return true;
 }
 \f
+/* Copy the program header and other data from one object module to
+   another.  */
+
+boolean
+_bfd_elf_copy_private_bfd_data (ibfd, obfd)
+     bfd *ibfd;
+     bfd *obfd;
+{
+  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+    return true;
+
+  BFD_ASSERT (!elf_flags_init (obfd)
+             || (elf_elfheader (obfd)->e_flags
+                 == elf_elfheader (ibfd)->e_flags));
+
+  elf_gp (obfd) = elf_gp (ibfd);
+  elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
+  elf_flags_init (obfd) = true;
+  return true;
+}
+
 /* Print out the program headers.  */
 
 boolean
@@ -798,6 +839,7 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
            case PT_NOTE: pt = "NOTE"; break;
            case PT_SHLIB: pt = "SHLIB"; break;
            case PT_PHDR: pt = "PHDR"; break;
+           case PT_GNU_EH_FRAME: pt = "EH_FRAME"; break;
            default: sprintf (buf, "0x%lx", p->p_type); pt = buf; break;
            }
          fprintf (f, "%8s off    0x", pt);
@@ -1534,6 +1576,20 @@ bfd_section_from_shdr (abfd, shindex)
         section, so that objcopy can handle it.  */
       return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
 
+    case SHT_SYMTAB_SHNDX:     /* Symbol section indices when >64k sections */
+      if (elf_symtab_shndx (abfd) == shindex)
+       return true;
+
+      /* Get the associated symbol table.  */
+      if (! bfd_section_from_shdr (abfd, hdr->sh_link)
+         || hdr->sh_link != elf_onesymtab (abfd))
+       return false;
+
+      elf_symtab_shndx (abfd) = shindex;
+      elf_tdata (abfd)->symtab_shndx_hdr = *hdr;
+      elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->symtab_shndx_hdr;
+      return true;
+
     case SHT_STRTAB:           /* A string table */
       if (hdr->bfd_section != NULL)
        return true;
@@ -1544,9 +1600,10 @@ bfd_section_from_shdr (abfd, shindex)
          return true;
        }
       {
-       unsigned int i;
+       unsigned int i, num_sec;
 
-       for (i = 1; i < ehdr->e_shnum; i++)
+       num_sec = elf_numsections (abfd);
+       for (i = 1; i < num_sec; i++)
          {
            Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
            if (hdr2->sh_link == shindex)
@@ -1592,9 +1649,11 @@ bfd_section_from_shdr (abfd, shindex)
       {
        asection *target_sect;
        Elf_Internal_Shdr *hdr2;
+       unsigned int num_sec = elf_numsections (abfd);
 
        /* Check for a bogus link to avoid crashing.  */
-       if (hdr->sh_link >= ehdr->e_shnum)
+       if ((hdr->sh_link >= SHN_LORESERVE && hdr->sh_link <= SHN_HIRESERVE)
+           || hdr->sh_link >= num_sec)
          {
            ((*_bfd_error_handler)
             (_("%s: invalid link %lu for reloc section %s (index %u)"),
@@ -1612,11 +1671,11 @@ bfd_section_from_shdr (abfd, shindex)
        if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_SYMTAB
            && elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_DYNSYM)
          {
-           int scan;
+           unsigned int scan;
            int found;
 
            found = 0;
-           for (scan = 1; scan < ehdr->e_shnum; scan++)
+           for (scan = 1; scan < num_sec; scan++)
              {
                if (elf_elfsections (abfd)[scan]->sh_type == SHT_SYMTAB
                    || elf_elfsections (abfd)[scan]->sh_type == SHT_DYNSYM)
@@ -1733,6 +1792,78 @@ bfd_section_from_shdr (abfd, shindex)
   return true;
 }
 
+/* Return the section for the local symbol specified by ABFD, R_SYMNDX.
+   Return SEC for sections that have no elf section, and NULL on error.  */
+
+asection *
+bfd_section_from_r_symndx (abfd, cache, sec, r_symndx)
+     bfd *abfd;
+     struct sym_sec_cache *cache;
+     asection *sec;
+     unsigned long r_symndx;
+{
+  unsigned char esym_shndx[4];
+  unsigned int isym_shndx;
+  Elf_Internal_Shdr *symtab_hdr;
+  file_ptr pos;
+  bfd_size_type amt;
+  unsigned int ent = r_symndx % LOCAL_SYM_CACHE_SIZE;
+
+  if (cache->abfd == abfd && cache->indx[ent] == r_symndx)
+    return cache->sec[ent];
+
+  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  pos = symtab_hdr->sh_offset;
+  if (get_elf_backend_data (abfd)->s->sizeof_sym
+      == sizeof (Elf64_External_Sym))
+    {
+      pos += r_symndx * sizeof (Elf64_External_Sym);
+      pos += offsetof (Elf64_External_Sym, st_shndx);
+      amt = sizeof (((Elf64_External_Sym *) 0)->st_shndx);
+    }
+  else
+    {
+      pos += r_symndx * sizeof (Elf32_External_Sym);
+      pos += offsetof (Elf32_External_Sym, st_shndx);
+      amt = sizeof (((Elf32_External_Sym *) 0)->st_shndx);
+    }
+  if (bfd_seek (abfd, pos, SEEK_SET) != 0
+      || bfd_bread ((PTR) esym_shndx, amt, abfd) != amt)
+    return NULL;
+  isym_shndx = H_GET_16 (abfd, esym_shndx);
+
+  if (isym_shndx == SHN_XINDEX)
+    {
+      Elf_Internal_Shdr *shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+      if (shndx_hdr->sh_size != 0)
+       {
+         pos = shndx_hdr->sh_offset;
+         pos += r_symndx * sizeof (Elf_External_Sym_Shndx);
+         amt = sizeof (Elf_External_Sym_Shndx);
+         if (bfd_seek (abfd, pos, SEEK_SET) != 0
+             || bfd_bread ((PTR) esym_shndx, amt, abfd) != amt)
+           return NULL;
+         isym_shndx = H_GET_32 (abfd, esym_shndx);
+       }
+    }
+
+  if (cache->abfd != abfd)
+    {
+      memset (cache->indx, -1, sizeof (cache->indx));
+      cache->abfd = abfd;
+    }
+  cache->indx[ent] = r_symndx;
+  cache->sec[ent] = sec;
+  if (isym_shndx < SHN_LORESERVE || isym_shndx > SHN_HIRESERVE)
+    {
+      asection *s;
+      s = bfd_section_from_elf_index (abfd, isym_shndx);
+      if (s != NULL)
+       cache->sec[ent] = s;
+    }
+  return cache->sec[ent];
+}
+
 /* Given an ELF section number, retrieve the corresponding BFD
    section.  */
 
@@ -1741,8 +1872,7 @@ bfd_section_from_elf_index (abfd, index)
      bfd *abfd;
      unsigned int index;
 {
-  BFD_ASSERT (index > 0 && index < SHN_LORESERVE);
-  if (index >= elf_elfheader (abfd)->e_shnum)
+  if (index >= elf_numsections (abfd))
     return NULL;
   return elf_elfsections (abfd)[index]->bfd_section;
 }
@@ -1925,8 +2055,8 @@ _bfd_elf_init_reloc_shdr (abfd, rel_hdr, asect, use_rela_p)
     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);
+    (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), name,
+                                       false);
   if (rel_hdr->sh_name == (unsigned int) -1)
     return false;
   rel_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL;
@@ -1963,9 +2093,8 @@ elf_fake_sections (abfd, asect, failedptrarg)
 
   this_hdr = &elf_section_data (asect)->this_hdr;
 
-  this_hdr->sh_name = (unsigned long) _bfd_stringtab_add (elf_shstrtab (abfd),
-                                                         asect->name,
-                                                         true, false);
+  this_hdr->sh_name = (unsigned long) _bfd_elf_strtab_add (elf_shstrtab (abfd),
+                                                          asect->name, false);
   if (this_hdr->sh_name == (unsigned long) -1)
     {
       *failedptr = true;
@@ -2186,39 +2315,79 @@ assign_section_numbers (abfd)
 {
   struct elf_obj_tdata *t = elf_tdata (abfd);
   asection *sec;
-  unsigned int section_number;
+  unsigned int section_number, secn;
   Elf_Internal_Shdr **i_shdrp;
   bfd_size_type amt;
 
   section_number = 1;
 
+  _bfd_elf_strtab_clear_all_refs (elf_shstrtab (abfd));
+
   for (sec = abfd->sections; sec; sec = sec->next)
     {
       struct bfd_elf_section_data *d = elf_section_data (sec);
 
+      if (section_number == SHN_LORESERVE)
+       section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
       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
-       d->rel_idx = section_number++;
+       {
+         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)
-       d->rel_idx2 = section_number++;
+       {
+         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);
+       }
       else
        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;
-  t->shstrtab_hdr.sh_size = _bfd_stringtab_size (elf_shstrtab (abfd));
 
   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)
+           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),
+                                                 ".symtab_shndx", false);
+         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);
     }
 
+  _bfd_elf_strtab_finalize (elf_shstrtab (abfd));
+  t->shstrtab_hdr.sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd));
+
+  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.  */
@@ -2242,6 +2411,11 @@ assign_section_numbers (abfd)
   if (bfd_get_symcount (abfd) > 0)
     {
       i_shdrp[t->symtab_section] = &t->symtab_hdr;
+      if (elf_numsections (abfd) > SHN_LORESERVE)
+       {
+         i_shdrp[t->symtab_shndx_section] = &t->symtab_shndx_hdr;
+         t->symtab_shndx_hdr.sh_link = t->symtab_section;
+       }
       i_shdrp[t->strtab_section] = &t->strtab_hdr;
       t->symtab_hdr.sh_link = t->strtab_section;
     }
@@ -2354,6 +2528,12 @@ assign_section_numbers (abfd)
        }
     }
 
+  for (secn = 1; secn < section_number; ++secn)
+    if (i_shdrp[secn] == NULL)
+      i_shdrp[secn] = i_shdrp[0];
+    else
+      i_shdrp[secn]->sh_name = _bfd_elf_strtab_offset (elf_shstrtab (abfd),
+                                                      i_shdrp[secn]->sh_name);
   return true;
 }
 
@@ -2615,7 +2795,7 @@ _bfd_elf_compute_section_file_positions (abfd, link_info)
   shstrtab_hdr->sh_type = SHT_STRTAB;
   shstrtab_hdr->sh_flags = 0;
   shstrtab_hdr->sh_addr = 0;
-  shstrtab_hdr->sh_size = _bfd_stringtab_size (elf_shstrtab (abfd));
+  shstrtab_hdr->sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd));
   shstrtab_hdr->sh_entsize = 0;
   shstrtab_hdr->sh_link = 0;
   shstrtab_hdr->sh_info = 0;
@@ -2635,6 +2815,10 @@ _bfd_elf_compute_section_file_positions (abfd, link_info)
       hdr = &elf_tdata (abfd)->symtab_hdr;
       off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
 
+      hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+      if (hdr->sh_size != 0)
+       off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+
       hdr = &elf_tdata (abfd)->strtab_hdr;
       off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
 
@@ -2708,7 +2892,7 @@ map_sections_to_segments (abfd)
   asection **hdrpp;
   boolean phdr_in_segment = true;
   boolean writable;
-  asection *dynsec;
+  asection *dynsec, *eh_frame_hdr;
   bfd_size_type amt;
 
   if (elf_tdata (abfd)->segment_map != NULL)
@@ -2948,6 +3132,26 @@ map_sections_to_segments (abfd)
        }
     }
 
+  /* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME
+     segment.  */
+  eh_frame_hdr = NULL;
+  if (elf_tdata (abfd)->eh_frame_hdr)
+    eh_frame_hdr = bfd_get_section_by_name (abfd, ".eh_frame_hdr");
+  if (eh_frame_hdr != NULL && (eh_frame_hdr->flags & SEC_LOAD))
+    {
+      amt = sizeof (struct elf_segment_map);
+      m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+      if (m == NULL)
+       goto error_return;
+      m->next = NULL;
+      m->p_type = PT_GNU_EH_FRAME;
+      m->count = 1;
+      m->sections[0] = eh_frame_hdr;
+
+      *pm = m;
+      pm = &m->next;
+    }
+
   free (sections);
   sections = NULL;
 
@@ -3095,8 +3299,13 @@ assign_file_positions_for_segments (abfd)
       asection **secpp;
 
       /* If elf_segment_map is not from map_sections_to_segments, the
-         sections may not be correctly ordered.  */
-      if (m->count > 0)
+         sections may not be correctly ordered.  NOTE: sorting should 
+        not be done to the PT_NOTE section of a corefile, which may
+        contain several pseudo-sections artificially created by bfd.
+        Sorting these pseudo-sections breaks things badly.  */
+      if (m->count > 1 
+         && !(elf_elfheader (abfd)->e_type == ET_CORE 
+              && m->p_type == PT_NOTE))
        qsort (m->sections, (size_t) m->count, sizeof (asection *),
               elf_sort_sections);
 
@@ -3248,10 +3457,10 @@ assign_file_positions_for_segments (abfd)
 
          /* The section may have artificial alignment forced by a
             link script.  Notice this case by the gap between the
-            cumulative phdr vma and the section's vma.  */
-         if (p->p_vaddr + p->p_memsz < sec->vma)
+            cumulative phdr lma and the section's lma.  */
+         if (p->p_paddr + p->p_memsz < sec->lma)
            {
-             bfd_vma adjust = sec->vma - (p->p_vaddr + p->p_memsz);
+             bfd_vma adjust = sec->lma - (p->p_paddr + p->p_memsz);
 
              p->p_memsz += adjust;
              off += adjust;
@@ -3289,13 +3498,11 @@ assign_file_positions_for_segments (abfd)
                {
                  if (i == 0)
                    {
-                     (* _bfd_error_handler)
-                       (_("Error: First section in segment (%s) starts at 0x%x"),
-                        bfd_section_name (abfd, sec), sec->lma);
-                     (* _bfd_error_handler)
-                       (_("       whereas segment starts at 0x%x"),
-                        p->p_paddr);
-
+                     (* _bfd_error_handler) (_("\
+Error: First section in segment (%s) starts at 0x%x whereas the segment starts at 0x%x"),
+                                             bfd_section_name (abfd, sec),
+                                             sec->lma,
+                                             p->p_paddr);
                      return false;
                    }
                  p->p_memsz += adjust;
@@ -3464,6 +3671,13 @@ get_program_header_size (abfd)
       ++segs;
     }
 
+  if (elf_tdata (abfd)->eh_frame_hdr
+      && bfd_get_section_by_name (abfd, ".eh_frame_hdr") != NULL)
+    {
+      /* We need a PT_GNU_EH_FRAME segment.  */
+      ++segs;
+    }
+
   for (s = abfd->sections; s != NULL; s = s->next)
     {
       if ((s->flags & SEC_LOAD) != 0
@@ -3507,6 +3721,7 @@ assign_file_positions_except_relocs (abfd)
   struct elf_obj_tdata * const tdata = elf_tdata (abfd);
   Elf_Internal_Ehdr * const i_ehdrp = elf_elfheader (abfd);
   Elf_Internal_Shdr ** const i_shdrpp = elf_elfsections (abfd);
+  unsigned int num_sec = elf_numsections (abfd);
   file_ptr off;
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
@@ -3522,24 +3737,27 @@ assign_file_positions_except_relocs (abfd)
       /* We are not creating an executable, which means that we are
         not creating a program header, and that the actual order of
         the sections in the file is unimportant.  */
-      for (i = 1, hdrpp = i_shdrpp + 1; i < i_ehdrp->e_shnum; i++, hdrpp++)
+      for (i = 1, hdrpp = i_shdrpp + 1; i < num_sec; i++, hdrpp++)
        {
          Elf_Internal_Shdr *hdr;
 
          hdr = *hdrpp;
-         if (hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
-           {
-             hdr->sh_offset = -1;
-             continue;
-           }
-         if (i == tdata->symtab_section
+         if (hdr->sh_type == SHT_REL
+             || hdr->sh_type == SHT_RELA
+             || i == tdata->symtab_section
+             || i == tdata->symtab_shndx_section
              || i == tdata->strtab_section)
            {
              hdr->sh_offset = -1;
-             continue;
            }
+         else
+           off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
 
-         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
@@ -3555,7 +3773,7 @@ assign_file_positions_except_relocs (abfd)
       /* Assign file positions for the other sections.  */
 
       off = elf_tdata (abfd)->next_file_pos;
-      for (i = 1, hdrpp = i_shdrpp + 1; i < i_ehdrp->e_shnum; i++, hdrpp++)
+      for (i = 1, hdrpp = i_shdrpp + 1; i < num_sec; i++, hdrpp++)
        {
          Elf_Internal_Shdr *hdr;
 
@@ -3581,10 +3799,17 @@ assign_file_positions_except_relocs (abfd)
          else if (hdr->sh_type == SHT_REL
                   || hdr->sh_type == SHT_RELA
                   || hdr == i_shdrpp[tdata->symtab_section]
+                  || hdr == i_shdrpp[tdata->symtab_shndx_section]
                   || hdr == i_shdrpp[tdata->strtab_section])
            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;
+           }
        }
     }
 
@@ -3606,13 +3831,13 @@ prep_headers (abfd)
   Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */
   Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */
   int count;
-  struct bfd_strtab_hash *shstrtab;
+  struct elf_strtab_hash *shstrtab;
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   i_ehdrp = elf_elfheader (abfd);
   i_shdrp = elf_elfsections (abfd);
 
-  shstrtab = _bfd_elf_stringtab_init ();
+  shstrtab = _bfd_elf_strtab_init ();
   if (shstrtab == NULL)
     return false;
 
@@ -3698,11 +3923,11 @@ prep_headers (abfd)
     }
 
   elf_tdata (abfd)->symtab_hdr.sh_name =
-    (unsigned int) _bfd_stringtab_add (shstrtab, ".symtab", true, false);
+    (unsigned int) _bfd_elf_strtab_add (shstrtab, ".symtab", false);
   elf_tdata (abfd)->strtab_hdr.sh_name =
-    (unsigned int) _bfd_stringtab_add (shstrtab, ".strtab", true, false);
+    (unsigned int) _bfd_elf_strtab_add (shstrtab, ".strtab", false);
   elf_tdata (abfd)->shstrtab_hdr.sh_name =
-    (unsigned int) _bfd_stringtab_add (shstrtab, ".shstrtab", true, false);
+    (unsigned int) _bfd_elf_strtab_add (shstrtab, ".shstrtab", false);
   if (elf_tdata (abfd)->symtab_hdr.sh_name == (unsigned int) -1
       || elf_tdata (abfd)->symtab_hdr.sh_name == (unsigned int) -1
       || elf_tdata (abfd)->shstrtab_hdr.sh_name == (unsigned int) -1)
@@ -3719,14 +3944,13 @@ _bfd_elf_assign_file_positions_for_relocs (abfd)
      bfd *abfd;
 {
   file_ptr off;
-  unsigned int i;
+  unsigned int i, num_sec;
   Elf_Internal_Shdr **shdrpp;
 
   off = elf_tdata (abfd)->next_file_pos;
 
-  for (i = 1, shdrpp = elf_elfsections (abfd) + 1;
-       i < elf_elfheader (abfd)->e_shnum;
-       i++, shdrpp++)
+  num_sec = elf_numsections (abfd);
+  for (i = 1, shdrpp = elf_elfsections (abfd) + 1; i < num_sec; i++, shdrpp++)
     {
       Elf_Internal_Shdr *shdrp;
 
@@ -3747,7 +3971,7 @@ _bfd_elf_write_object_contents (abfd)
   Elf_Internal_Ehdr *i_ehdrp;
   Elf_Internal_Shdr **i_shdrp;
   boolean failed;
-  unsigned int count;
+  unsigned int count, num_sec;
 
   if (! abfd->output_has_begun
       && ! _bfd_elf_compute_section_file_positions
@@ -3765,7 +3989,8 @@ _bfd_elf_write_object_contents (abfd)
   _bfd_elf_assign_file_positions_for_relocs (abfd);
 
   /* After writing the headers, we need to write the sections too...  */
-  for (count = 1; count < i_ehdrp->e_shnum; count++)
+  num_sec = elf_numsections (abfd);
+  for (count = 1; count < num_sec; count++)
     {
       if (bed->elf_backend_section_processing)
        (*bed->elf_backend_section_processing) (abfd, i_shdrp[count]);
@@ -3777,11 +4002,13 @@ _bfd_elf_write_object_contents (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.  */
   if (bfd_seek (abfd, elf_tdata (abfd)->shstrtab_hdr.sh_offset, SEEK_SET) != 0
-      || ! _bfd_stringtab_emit (abfd, elf_shstrtab (abfd)))
+      || ! _bfd_elf_strtab_emit (abfd, elf_shstrtab (abfd)))
     return false;
 
   if (bed->elf_backend_final_write_processing)
@@ -3810,12 +4037,23 @@ _bfd_elf_section_from_bfd_section (abfd, asect)
   Elf_Internal_Shdr **i_shdrp = elf_elfsections (abfd);
   int index;
   Elf_Internal_Shdr *hdr;
-  int maxindex = elf_elfheader (abfd)->e_shnum;
+  int maxindex = elf_numsections (abfd);
 
-  for (index = 0; index < maxindex; index++)
+  if (elf_section_data (asect) != NULL
+      && elf_section_data (asect)->this_idx != 0)
+    return elf_section_data (asect)->this_idx;
+
+  if (bfd_is_abs_section (asect))
+    return SHN_ABS;
+  if (bfd_is_com_section (asect))
+    return SHN_COMMON;
+  if (bfd_is_und_section (asect))
+    return SHN_UNDEF;
+
+  for (index = 1; index < maxindex; index++)
     {
       hdr = i_shdrp[index];
-      if (hdr->bfd_section == asect)
+      if (hdr != NULL && hdr->bfd_section == asect)
        return index;
     }
 
@@ -3826,6 +4064,9 @@ _bfd_elf_section_from_bfd_section (abfd, asect)
          int retval;
 
          hdr = i_shdrp[index];
+         if (hdr == NULL)
+           continue;
+
          retval = index;
          if ((*bed->elf_backend_section_from_bfd_section)
              (abfd, hdr, asect, &retval))
@@ -3833,16 +4074,9 @@ _bfd_elf_section_from_bfd_section (abfd, asect)
        }
     }
 
-  if (bfd_is_abs_section (asect))
-    return SHN_ABS;
-  if (bfd_is_com_section (asect))
-    return SHN_COMMON;
-  if (bfd_is_und_section (asect))
-    return SHN_UNDEF;
-
   bfd_set_error (bfd_error_nonrepresentable_section);
 
-  return -1;
+  return SHN_BAD;
 }
 
 /* Given a BFD symbol, return the index in the ELF symbol table, or -1
@@ -3980,16 +4214,19 @@ copy_private_bfd_data (ibfd, obfd)
 
   /* Decide if the given section should be included in the given segment.
      A section will be included if:
-       1. It is within the address space of the segment,
+       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,
        3. There is an output section associated with it,
        4. The section has not already been allocated to a previous segment.  */
-#define INCLUDE_SECTION_IN_SEGMENT(section, segment)   \
-  ((((IS_CONTAINED_BY_VMA (section, segment)           \
-      || IS_SOLARIS_PT_INTERP (segment, section))      \
-     && (section->flags & SEC_ALLOC) != 0)             \
-    || IS_COREFILE_NOTE (segment, section))            \
-   && section->output_section != NULL                  \
+#define INCLUDE_SECTION_IN_SEGMENT(section, segment)                   \
+  (((((segment->p_paddr                                                        \
+       ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr)      \
+       : IS_CONTAINED_BY_VMA (section, segment))                       \
+      || IS_SOLARIS_PT_INTERP (segment, section))                      \
+     && (section->flags & SEC_ALLOC) != 0)                             \
+    || IS_COREFILE_NOTE (segment, section))                            \
+   && section->output_section != NULL                                  \
    && section->segment_mark == false)
 
   /* Returns true iff seg1 starts after the end of seg2.  */
@@ -4006,7 +4243,7 @@ copy_private_bfd_data (ibfd, obfd)
 
   /* Scan through the segments specified in the program header
      of the input BFD.  For this first scan we look for overlaps
-     in the loadable segments.  These can be created by wierd
+     in the loadable segments.  These can be created by weird
      parameters to objcopy.  */
   for (i = 0, segment = elf_tdata (ibfd)->phdr;
        i < num_segments;
@@ -4408,7 +4645,7 @@ copy_private_bfd_data (ibfd, obfd)
   elf_tdata (obfd)->segment_map = map_first;
 
   /* If we had to estimate the number of program headers that were
-     going to be needed, then check our estimate know and adjust
+     going to be needed, then check our estimate now and adjust
      the offset if necessary.  */
   if (phdr_adjust_seg != NULL)
     {
@@ -4521,10 +4758,11 @@ _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
    section indices; these definitions are interpreted by the
    swap_out_syms function.  */
 
-#define MAP_ONESYMTAB (SHN_LORESERVE - 1)
-#define MAP_DYNSYMTAB (SHN_LORESERVE - 2)
-#define MAP_STRTAB (SHN_LORESERVE - 3)
-#define MAP_SHSTRTAB (SHN_LORESERVE - 4)
+#define MAP_ONESYMTAB (SHN_HIOS + 1)
+#define MAP_DYNSYMTAB (SHN_HIOS + 2)
+#define MAP_STRTAB    (SHN_HIOS + 3)
+#define MAP_SHSTRTAB  (SHN_HIOS + 4)
+#define MAP_SYM_SHNDX (SHN_HIOS + 5)
 
 boolean
 _bfd_elf_copy_private_symbol_data (ibfd, isymarg, obfd, osymarg)
@@ -4557,6 +4795,8 @@ _bfd_elf_copy_private_symbol_data (ibfd, isymarg, obfd, osymarg)
        shndx = MAP_STRTAB;
       else if (shndx == elf_tdata (ibfd)->shstrtab_section)
        shndx = MAP_SHSTRTAB;
+      else if (shndx == elf_tdata (ibfd)->symtab_shndx_section)
+       shndx = MAP_SYM_SHNDX;
       osym->internal_elf_sym.st_shndx = shndx;
     }
 
@@ -4576,8 +4816,10 @@ swap_out_syms (abfd, sttp, relocatable_p)
   asymbol **syms;
   struct bfd_strtab_hash *stt;
   Elf_Internal_Shdr *symtab_hdr;
+  Elf_Internal_Shdr *symtab_shndx_hdr;
   Elf_Internal_Shdr *symstrtab_hdr;
   char *outbound_syms;
+  char *outbound_shndx;
   int idx;
   bfd_size_type amt;
 
@@ -4607,6 +4849,22 @@ swap_out_syms (abfd, sttp, relocatable_p)
     return false;
   symtab_hdr->contents = (PTR) outbound_syms;
 
+  outbound_shndx = NULL;
+  symtab_shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+  if (symtab_shndx_hdr->sh_name != 0)
+    {
+      amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx);
+      outbound_shndx = bfd_alloc (abfd, amt);
+      if (outbound_shndx == NULL)
+       return false;
+      memset (outbound_shndx, 0, (unsigned long) amt);
+      symtab_shndx_hdr->contents = outbound_shndx;
+      symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
+      symtab_shndx_hdr->sh_size = amt;
+      symtab_shndx_hdr->sh_addralign = sizeof (Elf_External_Sym_Shndx);
+      symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
+    }
+
   /* now generate the data (for "contents") */
   {
     /* Fill in zeroth symbol and swap it out.  */
@@ -4617,8 +4875,10 @@ swap_out_syms (abfd, sttp, relocatable_p)
     sym.st_info = 0;
     sym.st_other = 0;
     sym.st_shndx = SHN_UNDEF;
-    bed->s->swap_symbol_out (abfd, &sym, (PTR) outbound_syms);
+    bed->s->swap_symbol_out (abfd, &sym, outbound_syms, outbound_shndx);
     outbound_syms += bed->s->sizeof_sym;
+    if (outbound_shndx != NULL)
+      outbound_shndx += sizeof (Elf_External_Sym_Shndx);
   }
 
   syms = bfd_get_outsymbols (abfd);
@@ -4699,6 +4959,9 @@ swap_out_syms (abfd, sttp, relocatable_p)
                case MAP_SHSTRTAB:
                  shndx = elf_tdata (abfd)->shstrtab_section;
                  break;
+               case MAP_SYM_SHNDX:
+                 shndx = elf_tdata (abfd)->symtab_shndx_section;
+                 break;
                default:
                  break;
                }
@@ -4776,8 +5039,10 @@ swap_out_syms (abfd, sttp, relocatable_p)
       else
        sym.st_other = 0;
 
-      bed->s->swap_symbol_out (abfd, &sym, (PTR) outbound_syms);
+      bed->s->swap_symbol_out (abfd, &sym, outbound_syms, outbound_shndx);
       outbound_syms += bed->s->sizeof_sym;
+      if (outbound_shndx != NULL)
+       outbound_shndx += sizeof (Elf_External_Sym_Shndx);
     }
 
   *sttp = stt;
@@ -5532,7 +5797,7 @@ _bfd_elf_close_and_cleanup (abfd)
   if (bfd_get_format (abfd) == bfd_object)
     {
       if (elf_shstrtab (abfd) != NULL)
-       _bfd_stringtab_free (elf_shstrtab (abfd));
+       _bfd_elf_strtab_free (elf_shstrtab (abfd));
     }
 
   return _bfd_generic_close_and_cleanup (abfd);
@@ -5664,7 +5929,10 @@ elfcore_grok_prstatus (abfd, note)
       offset   = offsetof (prstatus_t, pr_reg);
       memcpy (&prstat, note->descdata, sizeof (prstat));
 
-      elf_tdata (abfd)->core_signal = prstat.pr_cursig;
+      /* Do not overwrite the core signal if it
+        has already been set by another thread.  */
+      if (elf_tdata (abfd)->core_signal == 0)
+       elf_tdata (abfd)->core_signal = prstat.pr_cursig;
       elf_tdata (abfd)->core_pid = prstat.pr_pid;
 
       /* pr_who exists on:
@@ -5687,7 +5955,10 @@ elfcore_grok_prstatus (abfd, note)
       offset   = offsetof (prstatus32_t, pr_reg);
       memcpy (&prstat, note->descdata, sizeof (prstat));
 
-      elf_tdata (abfd)->core_signal = prstat.pr_cursig;
+      /* Do not overwrite the core signal if it
+        has already been set by another thread.  */
+      if (elf_tdata (abfd)->core_signal == 0)
+       elf_tdata (abfd)->core_signal = prstat.pr_cursig;
       elf_tdata (abfd)->core_pid = prstat.pr_pid;
 
       /* pr_who exists on:
@@ -6113,6 +6384,109 @@ elfcore_grok_note (abfd, note)
     }
 }
 
+static boolean
+elfcore_netbsd_get_lwpid (note, lwpidp)
+     Elf_Internal_Note *note;
+     int *lwpidp;
+{
+  char *cp;
+
+  cp = strchr (note->namedata, '@');
+  if (cp != NULL)
+    {
+      *lwpidp = atoi(cp);
+      return true;
+    }
+  return false;
+}
+
+static boolean
+elfcore_grok_netbsd_procinfo (abfd, note)
+     bfd *abfd;
+     Elf_Internal_Note *note;
+{
+
+  /* Signal number at offset 0x08. */
+  elf_tdata (abfd)->core_signal
+    = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x08);
+
+  /* Process ID at offset 0x50. */
+  elf_tdata (abfd)->core_pid
+    = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x50);
+
+  /* Command name at 0x7c (max 32 bytes, including nul). */
+  elf_tdata (abfd)->core_command
+    = _bfd_elfcore_strndup (abfd, note->descdata + 0x7c, 31);
+
+  return true;
+}
+
+static boolean
+elfcore_grok_netbsd_note (abfd, note)
+     bfd *abfd;
+     Elf_Internal_Note *note;
+{
+  int lwp;
+
+  if (elfcore_netbsd_get_lwpid (note, &lwp))
+    elf_tdata (abfd)->core_lwpid = lwp;
+
+  if (note->type == 1)
+    {
+      /* NetBSD-specific core "procinfo".  Note that we expect to
+         find this note before any of the others, which is fine,
+         since the kernel writes this note out first when it
+         creates a core file.  */
+      
+      return elfcore_grok_netbsd_procinfo (abfd, note);
+    }
+
+  /* There are not currently any other machine-independent notes defined
+     for NetBSD ELF core files.  If the note type is less than the start
+     of the machine-dependent note types, we don't understand it.  */
+  
+  if (note->type < 32)
+    return true;
+
+
+  switch (bfd_get_arch (abfd))
+    {
+    /* On the Alpha, SPARC (32-bit and 64-bit), PT_GETREGS == mach+0 and
+       PT_GETFPREGS == mach+2.  */
+
+    case bfd_arch_alpha:
+    case bfd_arch_sparc:
+      switch (note->type)
+        {
+        case 32+0:
+          return elfcore_make_note_pseudosection (abfd, ".reg", note);
+
+        case 32+2:
+          return elfcore_make_note_pseudosection (abfd, ".reg2", note);
+
+        default:
+          return true;
+        }
+
+    /* On all other arch's, PT_GETREGS == mach+1 and
+       PT_GETFPREGS == mach+3.  */
+
+    default:
+      switch (note->type)
+        {
+        case 32+1:
+          return elfcore_make_note_pseudosection (abfd, ".reg", note);
+
+        case 32+3:
+          return elfcore_make_note_pseudosection (abfd, ".reg2", note);
+
+        default:
+          return true;
+        }
+    }
+    /* NOTREACHED */
+}
+
 static boolean
 elfcore_read_notes (abfd, offset, size)
      bfd *abfd;
@@ -6155,8 +6529,16 @@ elfcore_read_notes (abfd, offset, size)
       in.descdata = in.namedata + BFD_ALIGN (in.namesz, 4);
       in.descpos = offset + (in.descdata - buf);
 
-      if (! elfcore_grok_note (abfd, &in))
-       goto error;
+      if (strncmp (in.namedata, "NetBSD-CORE", 11) == 0)
+        {
+          if (! elfcore_grok_netbsd_note (abfd, &in))
+            goto error;
+        }
+      else
+        {
+          if (! elfcore_grok_note (abfd, &in))
+            goto error;
+        }
 
       p = in.descdata + BFD_ALIGN (in.descsz, 4);
     }
@@ -6281,3 +6663,76 @@ _bfd_elf_reloc_type_class (rela)
 {
   return reloc_class_normal;
 }
+
+/* For RELA architectures, return what the relocation value for
+   relocation against a local symbol.  */
+
+bfd_vma
+_bfd_elf_rela_local_sym (abfd, sym, sec, rel)
+     bfd *abfd;
+     Elf_Internal_Sym *sym;
+     asection *sec;
+     Elf_Internal_Rela *rel;
+{
+  bfd_vma relocation;
+
+  relocation = (sec->output_section->vma
+               + sec->output_offset
+               + sym->st_value);
+  if ((sec->flags & SEC_MERGE)
+      && ELF_ST_TYPE (sym->st_info) == STT_SECTION
+      && elf_section_data (sec)->sec_info_type == ELF_INFO_TYPE_MERGE)
+    {
+      asection *msec;
+
+      msec = sec;
+      rel->r_addend =
+       _bfd_merged_section_offset (abfd, &msec,
+                                   elf_section_data (sec)->sec_info,
+                                   sym->st_value + rel->r_addend,
+                                   (bfd_vma) 0)
+       - relocation;
+      rel->r_addend += msec->output_section->vma + msec->output_offset;
+    }
+  return relocation;
+}
+
+bfd_vma
+_bfd_elf_rel_local_sym (abfd, sym, psec, addend)
+     bfd *abfd;
+     Elf_Internal_Sym *sym;
+     asection **psec;
+     bfd_vma addend;
+{     
+  asection *sec = *psec;
+
+  if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_MERGE)
+    return sym->st_value + addend;
+
+  return _bfd_merged_section_offset (abfd, psec,
+                                    elf_section_data (sec)->sec_info,
+                                    sym->st_value + addend, (bfd_vma) 0);
+}
+
+bfd_vma
+_bfd_elf_section_offset (abfd, info, sec, offset)
+     bfd *abfd;
+     struct bfd_link_info *info;
+     asection *sec;
+     bfd_vma offset;
+{
+  struct bfd_elf_section_data *sec_data;
+
+  sec_data = elf_section_data (sec);
+  switch (sec_data->sec_info_type)
+    {
+    case ELF_INFO_TYPE_STABS:
+      return _bfd_stab_section_offset
+       (abfd, &elf_hash_table (info)->merge_info, sec, &sec_data->sec_info,
+        offset);
+    case ELF_INFO_TYPE_EH_FRAME:
+      return _bfd_elf_eh_frame_section_offset (abfd, sec, offset);
+    default:
+      return offset;
+    }
+}
This page took 0.03632 seconds and 4 git commands to generate.