* pe-arm-wince.c (pe_print_compressed_pdata): Define new function to
[platform/upstream/binutils.git] / bfd / elf.c
index ffc82c7..d65c78d 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 *
@@ -271,7 +281,7 @@ bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
 
       /* Allocate and clear an extra byte at the end, to prevent crashes
         in case the string table is not terminated.  */
-      if (shstrtabsize + 1 == 0
+      if (shstrtabsize + 1 <= 1
          || (shstrtab = bfd_alloc (abfd, shstrtabsize + 1)) == NULL
          || bfd_seek (abfd, offset, SEEK_SET) != 0)
        shstrtab = NULL;
@@ -280,6 +290,10 @@ bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
          if (bfd_get_error () != bfd_error_system_call)
            bfd_set_error (bfd_error_file_truncated);
          shstrtab = NULL;
+         /* Once we've failed to read it, make sure we don't keep
+            trying.  Otherwise, we'll keep allocating space for
+            the string table over and over.  */
+         i_shdrp[shindex]->sh_size = 0;
        }
       else
        shstrtab[shstrtabsize] = '\0';
@@ -326,7 +340,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 +365,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;
 
@@ -442,8 +461,7 @@ bfd_elf_sym_name (bfd *abfd,
 
   if (iname == 0 && ELF_ST_TYPE (isym->st_info) == STT_SECTION
       /* Check for a bogus st_shndx to avoid crashing.  */
-      && isym->st_shndx < elf_numsections (abfd)
-      && !(isym->st_shndx >= SHN_LORESERVE && isym->st_shndx <= SHN_HIRESERVE))
+      && isym->st_shndx < elf_numsections (abfd))
     {
       iname = elf_elfsections (abfd)[isym->st_shndx]->sh_name;
       shindex = elf_elfheader (abfd)->e_shstrndx;
@@ -480,6 +498,8 @@ group_signature (bfd *abfd, Elf_Internal_Shdr *ghdr)
 
   /* First we need to ensure the symbol table is available.  Make sure
      that it is a symbol table section.  */
+  if (ghdr->sh_link >= elf_numsections (abfd))
+    return NULL;
   hdr = elf_elfsections (abfd) [ghdr->sh_link];
   if (hdr->sh_type != SHT_SYMTAB
       || ! bfd_section_from_shdr (abfd, ghdr->sh_link))
@@ -698,8 +718,7 @@ _bfd_elf_setup_sections (bfd *abfd)
             get the situation where elfsec is 0.  */
          if (elfsec == 0)
            {
-             const struct elf_backend_data *bed
-               = get_elf_backend_data (abfd);
+             const struct elf_backend_data *bed = get_elf_backend_data (abfd);
              if (bed->link_order_error_handler)
                bed->link_order_error_handler
                  (_("%B: warning: sh_link not set for section `%A'"),
@@ -707,14 +726,17 @@ _bfd_elf_setup_sections (bfd *abfd)
            }
          else
            {
-             asection *link;
+             asection *link = NULL;
 
-             this_hdr = elf_elfsections (abfd)[elfsec];
+             if (elfsec < elf_numsections (abfd))
+               {
+                 this_hdr = elf_elfsections (abfd)[elfsec];
+                 link = this_hdr->bfd_section;
+               }
 
              /* PR 1991, 2008:
                 Some strip/objcopy may leave an incorrect value in
                 sh_link.  We don't want to proceed.  */
-             link = this_hdr->bfd_section;
              if (link == NULL)
                {
                  (*_bfd_error_handler)
@@ -810,7 +832,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
   if (! bfd_set_section_vma (abfd, newsect, hdr->sh_addr)
       || ! bfd_set_section_size (abfd, newsect, hdr->sh_size)
       || ! bfd_set_section_alignment (abfd, newsect,
-                                     bfd_log2 ((bfd_vma) hdr->sh_addralign)))
+                                     bfd_log2 (hdr->sh_addralign)))
     return FALSE;
 
   flags = SEC_NO_FLAGS;
@@ -868,7 +890,14 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
          { NULL,                0  },  /* 'p' */
          { NULL,                0  },  /* 'q' */
          { NULL,                0  },  /* 'r' */
-         { STRING_COMMA_LEN ("stab") } /* 's' */
+         { STRING_COMMA_LEN ("stab") },        /* 's' */
+         { NULL,                0  },  /* 't' */
+         { NULL,                0  },  /* 'u' */
+         { NULL,                0  },  /* 'v' */
+         { NULL,                0  },  /* 'w' */
+         { NULL,                0  },  /* 'x' */
+         { NULL,                0  },  /* 'y' */
+         { STRING_COMMA_LEN ("zdebug") }       /* 'z' */
        };
 
       if (name [0] == '.')
@@ -926,65 +955,66 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
   if ((flags & SEC_ALLOC) != 0)
     {
       Elf_Internal_Phdr *phdr;
-      unsigned int i;
+      unsigned int i, nload;
+
+      /* Some ELF linkers produce binaries with all the program header
+        p_paddr fields zero.  If we have such a binary with more than
+        one PT_LOAD header, then leave the section lma equal to vma
+        so that we don't create sections with overlapping lma.  */
+      phdr = elf_tdata (abfd)->phdr;
+      for (nload = 0, i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
+       if (phdr->p_paddr != 0)
+         break;
+       else if (phdr->p_type == PT_LOAD && phdr->p_memsz != 0)
+         ++nload;
+      if (i >= elf_elfheader (abfd)->e_phnum && nload > 1)
+       return TRUE;
 
-      /* Look through the phdrs to see if we need to adjust the lma.
-        If all the p_paddr fields are zero, we ignore them, since
-        some ELF linkers produce such output.  */
       phdr = elf_tdata (abfd)->phdr;
       for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
        {
-         if (phdr->p_paddr != 0)
-           break;
-       }
-      if (i < elf_elfheader (abfd)->e_phnum)
-       {
-         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.
+
+            Note - we used to check the p_paddr field as well, and
+            refuse to set the LMA if it was 0.  This is wrong
+            though, as a perfectly valid initialised segment can
+            have a p_paddr of zero.  Some architectures, eg ARM,
+            place special significance on the address 0 and
+            executables need to be able to have a segment which
+            covers this address.  */
+         if (phdr->p_type == PT_LOAD
+             && (bfd_vma) hdr->sh_offset >= phdr->p_offset
+             && (hdr->sh_offset + hdr->sh_size
+                 <= phdr->p_offset + phdr->p_memsz)
+             && ((flags & SEC_LOAD) == 0
+                 || (hdr->sh_offset + hdr->sh_size
+                     <= phdr->p_offset + phdr->p_filesz)))
            {
-             /* 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.
-
-                Note - we used to check the p_paddr field as well, and
-                refuse to set the LMA if it was 0.  This is wrong
-                though, as a perfectly valid initialised segment can
-                have a p_paddr of zero.  Some architectures, eg ARM,
-                place special significance on the address 0 and
-                executables need to be able to have a segment which
-                covers this address.  */
-             if (phdr->p_type == PT_LOAD
-                 && (bfd_vma) hdr->sh_offset >= phdr->p_offset
-                 && (hdr->sh_offset + hdr->sh_size
-                     <= phdr->p_offset + phdr->p_memsz)
-                 && ((flags & SEC_LOAD) == 0
-                     || (hdr->sh_offset + hdr->sh_size
-                         <= phdr->p_offset + phdr->p_filesz)))
-               {
-                 if ((flags & SEC_LOAD) == 0)
-                   newsect->lma = (phdr->p_paddr
-                                   + hdr->sh_addr - phdr->p_vaddr);
-                 else
-                   /* We used to use the same adjustment for SEC_LOAD
-                      sections, but that doesn't work if the segment
-                      is packed with code from multiple VMAs.
-                      Instead we calculate the section LMA based on
-                      the segment LMA.  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);
-
-                 /* With contiguous segments, we can't tell from file
-                    offsets whether a section with zero size should
-                    be placed at the end of one segment or the
-                    beginning of the next.  Decide based on vaddr.  */
-                 if (hdr->sh_addr >= phdr->p_vaddr
-                     && (hdr->sh_addr + hdr->sh_size
-                         <= phdr->p_vaddr + phdr->p_memsz))
-                   break;
-               }
+             if ((flags & SEC_LOAD) == 0)
+               newsect->lma = (phdr->p_paddr
+                               + hdr->sh_addr - phdr->p_vaddr);
+             else
+               /* We used to use the same adjustment for SEC_LOAD
+                  sections, but that doesn't work if the segment
+                  is packed with code from multiple VMAs.
+                  Instead we calculate the section LMA based on
+                  the segment LMA.  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);
+
+             /* With contiguous segments, we can't tell from file
+                offsets whether a section with zero size should
+                be placed at the end of one segment or the
+                beginning of the next.  Decide based on vaddr.  */
+             if (hdr->sh_addr >= phdr->p_vaddr
+                 && (hdr->sh_addr + hdr->sh_size
+                     <= phdr->p_vaddr + phdr->p_memsz))
+               break;
            }
        }
     }
@@ -1165,7 +1195,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 +1207,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 +1219,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 +1233,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,9 +1303,12 @@ _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);
+           {
+             fprintf (f, "0x");
+             bfd_fprintf_vma (abfd, f, dyn.d_un.d_val);
+           }
          else
            {
              const char *string;
@@ -1496,17 +1536,22 @@ _bfd_elf_stringtab_init (void)
 bfd_boolean
 bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
 {
-  Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[shindex];
-  Elf_Internal_Ehdr *ehdr = elf_elfheader (abfd);
-  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  Elf_Internal_Shdr *hdr;
+  Elf_Internal_Ehdr *ehdr;
+  const struct elf_backend_data *bed;
   const char *name;
 
-  name = bfd_elf_string_from_elf_section (abfd,
-                                         elf_elfheader (abfd)->e_shstrndx,
+  if (shindex >= elf_numsections (abfd))
+    return FALSE;
+
+  hdr = elf_elfsections (abfd)[shindex];
+  ehdr = elf_elfheader (abfd);
+  name = bfd_elf_string_from_elf_section (abfd, ehdr->e_shstrndx,
                                          hdr->sh_name);
   if (name == NULL)
     return FALSE;
 
+  bed = get_elf_backend_data (abfd);
   switch (hdr->sh_type)
     {
     case SHT_NULL:
@@ -1707,8 +1752,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
          return FALSE;
 
        /* Check for a bogus link to avoid crashing.  */
-       if ((hdr->sh_link >= SHN_LORESERVE && hdr->sh_link <= SHN_HIRESERVE)
-           || hdr->sh_link >= num_sec)
+       if (hdr->sh_link >= num_sec)
          {
            ((*_bfd_error_handler)
             (_("%B: invalid link %lu for reloc section %s (index %u)"),
@@ -1762,7 +1806,6 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
           section, an invalid section, or another reloc section.  */
        if (hdr->sh_link != elf_onesymtab (abfd)
            || hdr->sh_info == SHN_UNDEF
-           || (hdr->sh_info >= SHN_LORESERVE && hdr->sh_info <= SHN_HIRESERVE)
            || hdr->sh_info >= num_sec
            || elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_REL
            || elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_RELA)
@@ -2083,6 +2126,15 @@ static const struct bfd_elf_special_section special_sections_t[] =
   { NULL,                     0,  0, 0,            0 }
 };
 
+static const struct bfd_elf_special_section special_sections_z[] =
+{
+  { STRING_COMMA_LEN (".zdebug_line"),    0, SHT_PROGBITS, 0 },
+  { STRING_COMMA_LEN (".zdebug_info"),    0, SHT_PROGBITS, 0 },
+  { STRING_COMMA_LEN (".zdebug_abbrev"),  0, SHT_PROGBITS, 0 },
+  { STRING_COMMA_LEN (".zdebug_aranges"), 0, SHT_PROGBITS, 0 },
+  { NULL,                     0,  0, 0,            0 }
+};
+
 static const struct bfd_elf_special_section *special_sections[] =
 {
   special_sections_b,          /* 'b' */
@@ -2104,6 +2156,12 @@ static const struct bfd_elf_special_section *special_sections[] =
   special_sections_r,          /* 'r' */
   special_sections_s,          /* 's' */
   special_sections_t,          /* 't' */
+  NULL,                                /* 'u' */
+  NULL,                                /* 'v' */
+  NULL,                                /* 'w' */
+  NULL,                                /* 'x' */
+  NULL,                                /* 'y' */
+  special_sections_z           /* 'z' */
 };
 
 const struct bfd_elf_special_section *
@@ -2180,7 +2238,7 @@ _bfd_elf_get_sec_type_attr (bfd *abfd, asection *sec)
     return NULL;
 
   i = sec->name[1] - 'b';
-  if (i < 0 || i > 't' - 'b')
+  if (i < 0 || i > 'z' - 'b')
     return NULL;
 
   spec = special_sections[i];
@@ -2421,7 +2479,7 @@ _bfd_elf_init_reloc_shdr (bfd *abfd,
   rel_hdr->sh_entsize = (use_rela_p
                         ? bed->s->sizeof_rela
                         : bed->s->sizeof_rel);
-  rel_hdr->sh_addralign = 1 << bed->s->log_file_align;
+  rel_hdr->sh_addralign = (bfd_vma) 1 << bed->s->log_file_align;
   rel_hdr->sh_flags = 0;
   rel_hdr->sh_addr = 0;
   rel_hdr->sh_size = 0;
@@ -2468,7 +2526,7 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg)
   this_hdr->sh_offset = 0;
   this_hdr->sh_size = asect->size;
   this_hdr->sh_link = 0;
-  this_hdr->sh_addralign = 1 << asect->alignment_power;
+  this_hdr->sh_addralign = (bfd_vma) 1 << asect->alignment_power;
   /* The sh_entsize and sh_info fields may have been set already by
      copy_private_section_data.  */
 
@@ -2749,11 +2807,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
                  abfd->section_count--;
                }
              else
-               {
-                 if (section_number == SHN_LORESERVE)
-                   section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
-                 d->this_idx = section_number++;
-               }
+               d->this_idx = section_number++;
            }
        }
     }
@@ -2763,26 +2817,18 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
       d = elf_section_data (sec);
 
       if (d->this_hdr.sh_type != SHT_GROUP)
-       {
-         if (section_number == SHN_LORESERVE)
-           section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
-         d->this_idx = section_number++;
-       }
+       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
        {
-         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)
        {
-         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);
        }
@@ -2790,22 +2836,16 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
        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;
 
   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 - 2) & 0xFFFF))
        {
-         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),
@@ -2813,8 +2853,6 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
          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);
     }
@@ -2824,8 +2862,6 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
 
   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.  */
@@ -2846,7 +2882,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
   if (bfd_get_symcount (abfd) > 0)
     {
       i_shdrp[t->symtab_section] = &t->symtab_hdr;
-      if (elf_numsections (abfd) > SHN_LORESERVE)
+      if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF))
        {
          i_shdrp[t->symtab_shndx_section] = &t->symtab_shndx_hdr;
          t->symtab_shndx_hdr.sh_link = t->symtab_section;
@@ -3064,17 +3100,15 @@ sym_is_global (bfd *abfd, asymbol *sym)
 }
 
 /* Don't output section symbols for sections that are not going to be
-   output.  Also, don't output section symbols for reloc and other
-   special sections.  */
+   output.  */
 
 static bfd_boolean
 ignore_section_sym (bfd *abfd, asymbol *sym)
 {
   return ((sym->flags & BSF_SECTION_SYM) != 0
-         && (sym->value != 0
-             || (sym->section->owner != abfd
-                 && (sym->section->output_section->owner != abfd
-                     || sym->section->output_offset != 0))));
+         && !(sym->section->owner == abfd
+              || (sym->section->output_section->owner == abfd
+                  && sym->section->output_offset == 0)));
 }
 
 static bfd_boolean
@@ -3117,6 +3151,7 @@ elf_map_symbols (bfd *abfd)
       asymbol *sym = syms[idx];
 
       if ((sym->flags & BSF_SECTION_SYM) != 0
+         && sym->value == 0
          && !ignore_section_sym (abfd, sym))
        {
          asection *sec = sym->section;
@@ -3215,14 +3250,8 @@ _bfd_elf_assign_file_position_for_section (Elf_Internal_Shdr *i_shdrp,
                                           file_ptr offset,
                                           bfd_boolean align)
 {
-  if (align)
-    {
-      unsigned int al;
-
-      al = i_shdrp->sh_addralign;
-      if (al > 1)
-       offset = BFD_ALIGN (offset, al);
-    }
+  if (align && i_shdrp->sh_addralign > 1)
+    offset = BFD_ALIGN (offset, i_shdrp->sh_addralign);
   i_shdrp->sh_offset = offset;
   if (i_shdrp->bfd_section != NULL)
     i_shdrp->bfd_section->filepos = offset;
@@ -3426,6 +3455,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 +4298,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;
@@ -4329,30 +4385,28 @@ assign_file_positions_for_load_sections (bfd *abfd,
          this_hdr = &elf_section_data (sec)->this_hdr;
          align = (bfd_size_type) 1 << bfd_get_section_alignment (abfd, sec);
 
-         if (p->p_type == PT_LOAD
-             || p->p_type == PT_TLS)
-           {
-             bfd_signed_vma adjust = sec->lma - (p->p_paddr + p->p_memsz);
-
-             if (this_hdr->sh_type != SHT_NOBITS
+         if ((p->p_type == PT_LOAD
+              || p->p_type == PT_TLS)
+             && (this_hdr->sh_type != SHT_NOBITS
                  || ((this_hdr->sh_flags & SHF_ALLOC) != 0
                      && ((this_hdr->sh_flags & SHF_TLS) == 0
-                         || p->p_type == PT_TLS)))
+                         || p->p_type == PT_TLS))))
+           {
+             bfd_signed_vma adjust = sec->vma - (p->p_vaddr + p->p_memsz);
+
+             if (adjust < 0)
                {
-                 if (adjust < 0)
-                   {
-                     (*_bfd_error_handler)
-                       (_("%B: section %A lma 0x%lx overlaps previous sections"),
-                        abfd, sec, (unsigned long) sec->lma);
-                     adjust = 0;
-                   }
-                 p->p_memsz += adjust;
+                 (*_bfd_error_handler)
+                   (_("%B: section %A vma 0x%lx overlaps previous sections"),
+                    abfd, sec, (unsigned long) sec->lma);
+                 adjust = 0;
+               }
+             p->p_memsz += adjust;
 
-                 if (this_hdr->sh_type != SHT_NOBITS)
-                   {
-                     off += adjust;
-                     p->p_filesz += adjust;
-                   }
+             if (this_hdr->sh_type != SHT_NOBITS)
+               {
+                 off += adjust;
+                 p->p_filesz += adjust;
                }
            }
 
@@ -4511,12 +4565,6 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
        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;
-       }
     }
 
   /* Now that we have set the section file positions, we can set up
@@ -4713,12 +4761,6 @@ assign_file_positions_except_relocs (bfd *abfd,
            }
          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;
-           }
        }
     }
   else
@@ -4764,12 +4806,10 @@ prep_headers (bfd *abfd)
 {
   Elf_Internal_Ehdr *i_ehdrp;  /* Elf file header, internal form */
   Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */
-  Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */
   struct elf_strtab_hash *shstrtab;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   i_ehdrp = elf_elfheader (abfd);
-  i_shdrp = elf_elfsections (abfd);
 
   shstrtab = _bfd_elf_strtab_init ();
   if (shstrtab == NULL)
@@ -4914,8 +4954,6 @@ _bfd_elf_write_object_contents (bfd *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.  */
@@ -4947,11 +4985,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 +5002,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 +5013,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;
@@ -5052,6 +5090,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
   unsigned int i;
   unsigned int num_segments;
   bfd_boolean phdr_included = FALSE;
+  bfd_boolean p_paddr_valid;
   bfd_vma maxpagesize;
   struct elf_segment_map *phdr_adjust_seg = NULL;
   unsigned int phdr_adjust_num = 0;
@@ -5090,15 +5129,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 +5163,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 +5177,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))                         \
@@ -5172,6 +5219,20 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
   for (section = ibfd->sections; section != NULL; section = section->next)
     section->segment_mark = FALSE;
 
+  /* The Solaris linker creates program headers in which all the
+     p_paddr fields are zero.  When we try to objcopy or strip such a
+     file, we get confused.  Check for this case, and if we find it
+     don't set the p_paddr_valid fields.  */
+  p_paddr_valid = FALSE;
+  for (i = 0, segment = elf_tdata (ibfd)->phdr;
+       i < num_segments;
+       i++, segment++)
+    if (segment->p_paddr != 0)
+      {
+       p_paddr_valid = TRUE;
+       break;
+      }
+
   /* 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 weird
@@ -5307,7 +5368,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
       if (!first_section || first_section->output_section != NULL)
        {
          map->p_paddr = segment->p_paddr;
-         map->p_paddr_valid = 1;
+         map->p_paddr_valid = p_paddr_valid;
        }
 
       /* Determine if this segment contains the ELF file header
@@ -5374,8 +5435,6 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
         pointers that we are interested in.  As these sections get assigned
         to a segment, they are removed from this array.  */
 
-      /* Gcc 2.96 miscompiles this code on mips. Don't do casting here
-        to work around this long long bug.  */
       sections = bfd_malloc2 (section_count, sizeof (asection *));
       if (sections == NULL)
        return FALSE;
@@ -5392,9 +5451,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))
            {
@@ -5406,7 +5469,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
                 We try to catch that case here, and set it to the
                 correct value.  Note - some backends require that
                 p_paddr be left as zero.  */
-             if (segment->p_paddr == 0
+             if (!p_paddr_valid
                  && segment->p_vaddr != 0
                  && !bed->want_p_paddr_set_to_zero
                  && isec == 0
@@ -5444,6 +5507,9 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
                  suggested_lma = output_section->lma;
                  first_suggested_lma = FALSE;
                }
+
+             if (j == section_count)
+               break;
            }
        }
 
@@ -5461,8 +5527,11 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
          *pointer_to_map = map;
          pointer_to_map = &map->next;
 
-         if (matching_lma != map->p_paddr
-             && !map->includes_filehdr && !map->includes_phdrs)
+         if (p_paddr_valid
+             && !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
               segment's vma.  */
@@ -5614,7 +5683,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
              map->p_flags = segment->p_flags;
              map->p_flags_valid = 1;
              map->p_paddr = suggested_lma;
-             map->p_paddr_valid = 1;
+             map->p_paddr_valid = p_paddr_valid;
              map->includes_filehdr = 0;
              map->includes_phdrs = 0;
            }
@@ -5624,17 +5693,6 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
       free (sections);
     }
 
-  /* The Solaris linker creates program headers in which all the
-     p_paddr fields are zero.  When we try to objcopy or strip such a
-     file, we get confused.  Check for this case, and if we find it
-     reset the p_paddr_valid fields.  */
-  for (map = map_first; map != NULL; map = map->next)
-    if (map->p_paddr != 0)
-      break;
-  if (map == NULL)
-    for (map = map_first; map != NULL; map = map->next)
-      map->p_paddr_valid = 0;
-
   elf_tdata (obfd)->segment_map = map_first;
 
   /* If we had to estimate the number of program headers that were
@@ -5656,6 +5714,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
@@ -5678,16 +5737,29 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
   unsigned int i;
   unsigned int num_segments;
   bfd_boolean phdr_included = FALSE;
+  bfd_boolean p_paddr_valid;
 
   iehdr = elf_elfheader (ibfd);
 
   map_first = NULL;
   pointer_to_map = &map_first;
 
+  /* If all the segment p_paddr fields are zero, don't set
+     map->p_paddr_valid.  */
+  p_paddr_valid = FALSE;
   num_segments = elf_elfheader (ibfd)->e_phnum;
   for (i = 0, segment = elf_tdata (ibfd)->phdr;
        i < num_segments;
        i++, segment++)
+    if (segment->p_paddr != 0)
+      {
+       p_paddr_valid = TRUE;
+       break;
+      }
+
+  for (i = 0, segment = elf_tdata (ibfd)->phdr;
+       i < num_segments;
+       i++, segment++)
     {
       asection *section;
       unsigned int section_count;
@@ -5728,7 +5800,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
       map->p_flags = segment->p_flags;
       map->p_flags_valid = 1;
       map->p_paddr = segment->p_paddr;
-      map->p_paddr_valid = 1;
+      map->p_paddr_valid = p_paddr_valid;
       map->p_align = segment->p_align;
       map->p_align_valid = 1;
       map->p_vaddr_offset = 0;
@@ -5762,7 +5834,9 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
            phdr_included = TRUE;
        }
 
-      if (!map->includes_phdrs && !map->includes_filehdr)
+      if (!map->includes_phdrs
+         && !map->includes_filehdr
+         && map->p_paddr_valid)
        /* There is some other padding before the first section.  */
        map->p_vaddr_offset = ((lowest_section ? lowest_section->lma : 0)
                               - segment->p_paddr);
@@ -5815,6 +5889,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 +6127,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))
     {
@@ -6103,7 +6185,7 @@ swap_out_syms (bfd *abfd,
   symtab_hdr->sh_entsize = bed->s->sizeof_sym;
   symtab_hdr->sh_size = symtab_hdr->sh_entsize * (symcount + 1);
   symtab_hdr->sh_info = elf_num_locals (abfd) + 1;
-  symtab_hdr->sh_addralign = 1 << bed->s->log_file_align;
+  symtab_hdr->sh_addralign = (bfd_vma) 1 << bed->s->log_file_align;
 
   symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
   symstrtab_hdr->sh_type = SHT_STRTAB;
@@ -6203,7 +6285,7 @@ swap_out_syms (bfd *abfd,
       else
        {
          asection *sec = syms[idx]->section;
-         int shndx;
+         unsigned int shndx;
 
          if (sec->output_section)
            {
@@ -6250,7 +6332,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 +6356,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 +6393,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
@@ -6477,8 +6563,7 @@ _bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
 
   ret = sizeof (arelent *);
   for (s = abfd->sections; s != NULL; s = s->next)
-    if ((s->flags & SEC_LOAD) != 0
-       && elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
+    if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
        && (elf_section_data (s)->this_hdr.sh_type == SHT_REL
            || elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
       ret += ((s->size / elf_section_data (s)->this_hdr.sh_entsize)
@@ -6514,8 +6599,7 @@ _bfd_elf_canonicalize_dynamic_reloc (bfd *abfd,
   ret = 0;
   for (s = abfd->sections; s != NULL; s = s->next)
     {
-      if ((s->flags & SEC_LOAD) != 0
-         && elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
+      if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
          && (elf_section_data (s)->this_hdr.sh_type == SHT_REL
              || elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
        {
@@ -8390,6 +8474,23 @@ elfcore_write_ppc_vmx (bfd *abfd,
                             note_name, NT_PPC_VMX, ppc_vmx, size);
 }
 
+char *
+elfcore_write_register_note (bfd *abfd,
+                            char *buf,
+                            int *bufsiz,
+                            const char *section,
+                            const void *data,
+                            int size)
+{
+  if (strcmp (section, ".reg2") == 0)
+    return elfcore_write_prfpreg (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-xfp") == 0)
+    return elfcore_write_prxfpreg (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-ppc-vmx") == 0)
+    return elfcore_write_ppc_vmx (abfd, buf, bufsiz, data, size);
+  return NULL;
+}
+
 static bfd_boolean
 elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
 {
@@ -8682,7 +8783,7 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd,
   count = relplt->size / hdr->sh_entsize;
   size = count * sizeof (asymbol);
   p = relplt->relocation;
-  for (i = 0; i < count; i++, p++)
+  for (i = 0; i < count; i++, p += bed->s->int_rels_per_ext_rel)
     size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt");
 
   s = *ret = bfd_malloc (size);
@@ -8692,7 +8793,7 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd,
   names = (char *) (s + count);
   p = relplt->relocation;
   n = 0;
-  for (i = 0; i < count; i++, p++)
+  for (i = 0; i < count; i++, p += bed->s->int_rels_per_ext_rel)
     {
       size_t len;
       bfd_vma addr;
@@ -8706,6 +8807,7 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd,
         we are defining a symbol, ensure one of them is set.  */
       if ((s->flags & BSF_LOCAL) == 0)
        s->flags |= BSF_GLOBAL;
+      s->flags |= BSF_SYNTHETIC;
       s->section = plt;
       s->value = addr - plt->vma;
       s->name = names;