| Index: bfd/elf.c
 | 
| diff --git a/bfd/elf.c b/bfd/elf.c
 | 
| index f1e4882530d1ffb6944f175b94b90336abad0d2c..48e5d68341354e0d6915c8d9659e5cc6885d71d8 100644
 | 
| --- a/bfd/elf.c
 | 
| +++ b/bfd/elf.c
 | 
| @@ -1,7 +1,7 @@
 | 
|  /* ELF executable support for BFD.
 | 
|  
 | 
|     Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
 | 
| -   2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
 | 
| +   2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
 | 
|     Free Software Foundation, Inc.
 | 
|  
 | 
|     This file is part of BFD, the Binary File Descriptor library.
 | 
| @@ -1025,7 +1025,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
 | 
|        else
 | 
|  	{
 | 
|  	  /* Normal section.  Check if we should compress.  */
 | 
| -	  if ((abfd->flags & BFD_COMPRESS))
 | 
| +	  if ((abfd->flags & BFD_COMPRESS) && newsect->size != 0)
 | 
|  	    action = compress;
 | 
|  	}
 | 
|  
 | 
| @@ -1038,7 +1038,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
 | 
|  	  if (!bfd_init_section_compress_status (abfd, newsect))
 | 
|  	    {
 | 
|  	      (*_bfd_error_handler)
 | 
| -		(_("%B: unable to initialize commpress status for section %s"),
 | 
| +		(_("%B: unable to initialize compress status for section %s"),
 | 
|  		 abfd, name);
 | 
|  	      return FALSE;
 | 
|  	    }
 | 
| @@ -1058,7 +1058,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
 | 
|  	  if (!bfd_init_section_decompress_status (abfd, newsect))
 | 
|  	    {
 | 
|  	      (*_bfd_error_handler)
 | 
| -		(_("%B: unable to initialize decommpress status for section %s"),
 | 
| +		(_("%B: unable to initialize decompress status for section %s"),
 | 
|  		 abfd, name);
 | 
|  	      return FALSE;
 | 
|  	    }
 | 
| @@ -1646,7 +1646,15 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
 | 
|        if (hdr->sh_entsize != bed->s->sizeof_sym)
 | 
|  	return FALSE;
 | 
|        if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size)
 | 
| -	return FALSE;
 | 
| +	{
 | 
| +	  if (hdr->sh_size != 0)
 | 
| +	    return FALSE;
 | 
| +	  /* Some assemblers erroneously set sh_info to one with a
 | 
| +	     zero sh_size.  ld sees this as a global symbol count
 | 
| +	     of (unsigned) -1.  Fix it here.  */
 | 
| +	  hdr->sh_info = 0;
 | 
| +	  return TRUE;
 | 
| +	}
 | 
|        BFD_ASSERT (elf_onesymtab (abfd) == 0);
 | 
|        elf_onesymtab (abfd) = shindex;
 | 
|        elf_tdata (abfd)->symtab_hdr = *hdr;
 | 
| @@ -1699,6 +1707,16 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
 | 
|  
 | 
|        if (hdr->sh_entsize != bed->s->sizeof_sym)
 | 
|  	return FALSE;
 | 
| +      if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size)
 | 
| +	{
 | 
| +	  if (hdr->sh_size != 0)
 | 
| +	    return FALSE;
 | 
| +	  /* Some linkers erroneously set sh_info to one with a
 | 
| +	     zero sh_size.  ld sees this as a global symbol count
 | 
| +	     of (unsigned) -1.  Fix it here.  */
 | 
| +	  hdr->sh_info = 0;
 | 
| +	  return TRUE;
 | 
| +	}
 | 
|        BFD_ASSERT (elf_dynsymtab (abfd) == 0);
 | 
|        elf_dynsymtab (abfd) = shindex;
 | 
|        elf_tdata (abfd)->dynsymtab_hdr = *hdr;
 | 
| @@ -2527,7 +2545,7 @@ _bfd_elf_init_reloc_shdr (bfd *abfd,
 | 
|    rel_hdr = bfd_zalloc (abfd, amt);
 | 
|    reldata->hdr = rel_hdr;
 | 
|  
 | 
| -  amt = sizeof ".rela" + strlen (asect->name);      
 | 
| +  amt = sizeof ".rela" + strlen (asect->name);
 | 
|    name = (char *) bfd_alloc (abfd, amt);
 | 
|    if (name == NULL)
 | 
|      return FALSE;
 | 
| @@ -2996,6 +3014,13 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
 | 
|        _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->strtab_hdr.sh_name);
 | 
|      }
 | 
|  
 | 
| +  if (section_number >= SHN_LORESERVE)
 | 
| +    {
 | 
| +      _bfd_error_handler (_("%B: too many sections: %u"),
 | 
| +			  abfd, section_number);
 | 
| +      return FALSE;
 | 
| +    }
 | 
| +
 | 
|    _bfd_elf_strtab_finalize (elf_shstrtab (abfd));
 | 
|    t->shstrtab_hdr.sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd));
 | 
|  
 | 
| @@ -3071,7 +3096,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
 | 
|  	      if (link_info != NULL)
 | 
|  		{
 | 
|  		  /* Check discarded linkonce section.  */
 | 
| -		  if (elf_discarded_section (s))
 | 
| +		  if (discarded_section (s))
 | 
|  		    {
 | 
|  		      asection *kept;
 | 
|  		      (*_bfd_error_handler)
 | 
| @@ -3225,9 +3250,6 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
 | 
|    return TRUE;
 | 
|  }
 | 
|  
 | 
| -/* Map symbol from it's internal number to the external number, moving
 | 
| -   all local symbols to be at the head of the list.  */
 | 
| -
 | 
|  static bfd_boolean
 | 
|  sym_is_global (bfd *abfd, asymbol *sym)
 | 
|  {
 | 
| @@ -3242,7 +3264,7 @@ sym_is_global (bfd *abfd, asymbol *sym)
 | 
|  }
 | 
|  
 | 
|  /* Don't output section symbols for sections that are not going to be
 | 
| -   output.  */
 | 
| +   output, or that are duplicates.  */
 | 
|  
 | 
|  static bfd_boolean
 | 
|  ignore_section_sym (bfd *abfd, asymbol *sym)
 | 
| @@ -3250,9 +3272,13 @@ ignore_section_sym (bfd *abfd, asymbol *sym)
 | 
|    return ((sym->flags & BSF_SECTION_SYM) != 0
 | 
|  	  && !(sym->section->owner == abfd
 | 
|  	       || (sym->section->output_section->owner == abfd
 | 
| -		   && sym->section->output_offset == 0)));
 | 
| +		   && sym->section->output_offset == 0)
 | 
| +	       || bfd_is_abs_section (sym->section)));
 | 
|  }
 | 
|  
 | 
| +/* Map symbol from it's internal number to the external number, moving
 | 
| +   all local symbols to be at the head of the list.  */
 | 
| +
 | 
|  static bfd_boolean
 | 
|  elf_map_symbols (bfd *abfd)
 | 
|  {
 | 
| @@ -3294,7 +3320,8 @@ elf_map_symbols (bfd *abfd)
 | 
|  
 | 
|        if ((sym->flags & BSF_SECTION_SYM) != 0
 | 
|  	  && sym->value == 0
 | 
| -	  && !ignore_section_sym (abfd, sym))
 | 
| +	  && !ignore_section_sym (abfd, sym)
 | 
| +	  && !bfd_is_abs_section (sym->section))
 | 
|  	{
 | 
|  	  asection *sec = sym->section;
 | 
|  
 | 
| @@ -3308,12 +3335,10 @@ elf_map_symbols (bfd *abfd)
 | 
|    /* Classify all of the symbols.  */
 | 
|    for (idx = 0; idx < symcount; idx++)
 | 
|      {
 | 
| -      if (ignore_section_sym (abfd, syms[idx]))
 | 
| -	continue;
 | 
| -      if (!sym_is_global (abfd, syms[idx]))
 | 
| -	num_locals++;
 | 
| -      else
 | 
| +      if (sym_is_global (abfd, syms[idx]))
 | 
|  	num_globals++;
 | 
| +      else if (!ignore_section_sym (abfd, syms[idx]))
 | 
| +	num_locals++;
 | 
|      }
 | 
|  
 | 
|    /* We will be adding a section symbol for each normal BFD section.  Most
 | 
| @@ -3343,12 +3368,12 @@ elf_map_symbols (bfd *abfd)
 | 
|        asymbol *sym = syms[idx];
 | 
|        unsigned int i;
 | 
|  
 | 
| -      if (ignore_section_sym (abfd, sym))
 | 
| -	continue;
 | 
| -      if (!sym_is_global (abfd, sym))
 | 
| +      if (sym_is_global (abfd, sym))
 | 
| +	i = num_locals + num_globals2++;
 | 
| +      else if (!ignore_section_sym (abfd, sym))
 | 
|  	i = num_locals2++;
 | 
|        else
 | 
| -	i = num_locals + num_globals2++;
 | 
| +	continue;
 | 
|        new_syms[i] = sym;
 | 
|        sym->udata.i = i + 1;
 | 
|      }
 | 
| @@ -3744,6 +3769,10 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
 | 
|    bfd_boolean no_user_phdrs;
 | 
|  
 | 
|    no_user_phdrs = elf_tdata (abfd)->segment_map == NULL;
 | 
| +
 | 
| +  if (info != NULL)
 | 
| +    info->user_phdrs = !no_user_phdrs;
 | 
| +
 | 
|    if (no_user_phdrs && bfd_count_sections (abfd) != 0)
 | 
|      {
 | 
|        asection *s;
 | 
| @@ -4130,18 +4159,25 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
 | 
|  	{
 | 
|  	  for (m = mfirst; m != NULL; m = m->next)
 | 
|  	    {
 | 
| -	      if (m->p_type == PT_LOAD)
 | 
| +	      if (m->p_type == PT_LOAD
 | 
| +		  && m->count != 0
 | 
| +		  && m->sections[0]->vma >= info->relro_start
 | 
| +		  && m->sections[0]->vma < info->relro_end)
 | 
|  		{
 | 
| -		  asection *last = m->sections[m->count - 1];
 | 
| -		  bfd_vma vaddr = m->sections[0]->vma;
 | 
| -		  bfd_vma filesz = last->vma - vaddr + last->size;
 | 
| +		  i = m->count;
 | 
| +		  while (--i != (unsigned) -1)
 | 
| +		    if ((m->sections[i]->flags & (SEC_LOAD | SEC_HAS_CONTENTS))
 | 
| +			== (SEC_LOAD | SEC_HAS_CONTENTS))
 | 
| +		      break;
 | 
|  
 | 
| -		  if (vaddr < info->relro_end
 | 
| -		      && vaddr >= info->relro_start
 | 
| -		      && (vaddr + filesz) >= info->relro_end)
 | 
| +		  if (i == (unsigned) -1)
 | 
| +		    continue;
 | 
| +
 | 
| +		  if (m->sections[i]->vma + m->sections[i]->size
 | 
| +		      >= info->relro_end)
 | 
|  		    break;
 | 
|  		}
 | 
| -	      }
 | 
| +	    }
 | 
|  
 | 
|  	  /* Make a PT_GNU_RELRO segment only when it isn't empty.  */
 | 
|  	  if (m != NULL)
 | 
| @@ -4351,7 +4387,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
 | 
|        elf_elfheader (abfd)->e_phoff = 0;
 | 
|        elf_elfheader (abfd)->e_phentsize = 0;
 | 
|      }
 | 
| -  
 | 
| +
 | 
|    elf_elfheader (abfd)->e_phnum = alloc;
 | 
|  
 | 
|    if (elf_tdata (abfd)->program_header_size == (bfd_size_type) -1)
 | 
| @@ -4546,8 +4582,6 @@ assign_file_positions_for_load_sections (bfd *abfd,
 | 
|  	  p->p_memsz = bed->s->sizeof_ehdr;
 | 
|  	  if (m->count > 0)
 | 
|  	    {
 | 
| -	      BFD_ASSERT (p->p_type == PT_LOAD);
 | 
| -
 | 
|  	      if (p->p_vaddr < (bfd_vma) off)
 | 
|  		{
 | 
|  		  (*_bfd_error_handler)
 | 
| @@ -4574,7 +4608,6 @@ assign_file_positions_for_load_sections (bfd *abfd,
 | 
|  
 | 
|  	      if (m->count > 0)
 | 
|  		{
 | 
| -		  BFD_ASSERT (p->p_type == PT_LOAD);
 | 
|  		  p->p_vaddr -= off - p->p_offset;
 | 
|  		  if (!m->p_paddr_valid)
 | 
|  		    p->p_paddr -= off - p->p_offset;
 | 
| @@ -4797,6 +4830,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
 | 
|    Elf_Internal_Phdr *phdrs;
 | 
|    Elf_Internal_Phdr *p;
 | 
|    struct elf_segment_map *m;
 | 
| +  struct elf_segment_map *hdrs_segment;
 | 
|    bfd_vma filehdr_vaddr, filehdr_paddr;
 | 
|    bfd_vma phdrs_vaddr, phdrs_paddr;
 | 
|    file_ptr off;
 | 
| @@ -4820,12 +4854,13 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
 | 
|  	BFD_ASSERT (hdr->sh_offset == hdr->bfd_section->filepos);
 | 
|        else if ((hdr->sh_flags & SHF_ALLOC) != 0)
 | 
|  	{
 | 
| -	  (*_bfd_error_handler)
 | 
| -	    (_("%B: warning: allocated section `%s' not in segment"),
 | 
| -	     abfd,
 | 
| -	     (hdr->bfd_section == NULL
 | 
| -	      ? "*unknown*"
 | 
| -	      : hdr->bfd_section->name));
 | 
| +	  if (hdr->sh_size != 0)
 | 
| +	    (*_bfd_error_handler)
 | 
| +	      (_("%B: warning: allocated section `%s' not in segment"),
 | 
| +	       abfd,
 | 
| +	       (hdr->bfd_section == NULL
 | 
| +		? "*unknown*"
 | 
| +		: hdr->bfd_section->name));
 | 
|  	  /* We don't need to page align empty sections.  */
 | 
|  	  if ((abfd->flags & D_PAGED) != 0 && hdr->sh_size != 0)
 | 
|  	    off += vma_page_aligned_bias (hdr->sh_addr, off,
 | 
| @@ -4853,6 +4888,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
 | 
|    filehdr_paddr = 0;
 | 
|    phdrs_vaddr = bed->maxpagesize + bed->s->sizeof_ehdr;
 | 
|    phdrs_paddr = 0;
 | 
| +  hdrs_segment = NULL;
 | 
|    phdrs = elf_tdata (abfd)->phdr;
 | 
|    for (m = elf_tdata (abfd)->segment_map, p = phdrs;
 | 
|         m != NULL;
 | 
| @@ -4873,12 +4909,59 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
 | 
|  	  phdrs_paddr = p->p_paddr;
 | 
|  	  if (m->includes_filehdr)
 | 
|  	    {
 | 
| +	      hdrs_segment = m;
 | 
|  	      phdrs_vaddr += bed->s->sizeof_ehdr;
 | 
|  	      phdrs_paddr += bed->s->sizeof_ehdr;
 | 
|  	    }
 | 
|  	}
 | 
|      }
 | 
|  
 | 
| +  if (hdrs_segment != NULL && link_info != NULL)
 | 
| +    {
 | 
| +      /* There is a segment that contains both the file headers and the
 | 
| +	 program headers, so provide a symbol __ehdr_start pointing there.
 | 
| +	 A program can use this to examine itself robustly.  */
 | 
| +
 | 
| +      struct elf_link_hash_entry *hash
 | 
| +	= elf_link_hash_lookup (elf_hash_table (link_info), "__ehdr_start",
 | 
| +				FALSE, FALSE, TRUE);
 | 
| +      /* If the symbol was referenced and not defined, define it.  */
 | 
| +      if (hash != NULL
 | 
| +	  && (hash->root.type == bfd_link_hash_new
 | 
| +	      || hash->root.type == bfd_link_hash_undefined
 | 
| +	      || hash->root.type == bfd_link_hash_undefweak
 | 
| +	      || hash->root.type == bfd_link_hash_common))
 | 
| +	{
 | 
| +	  asection *s = NULL;
 | 
| +	  if (hdrs_segment->count != 0)
 | 
| +	    /* The segment contains sections, so use the first one.  */
 | 
| +	    s = hdrs_segment->sections[0];
 | 
| +	  else
 | 
| +	    /* Use the first (i.e. lowest-addressed) section in any segment.  */
 | 
| +	    for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
 | 
| +	      if (m->count != 0)
 | 
| +		{
 | 
| +		  s = m->sections[0];
 | 
| +		  break;
 | 
| +		}
 | 
| +
 | 
| +	  if (s != NULL)
 | 
| +	    {
 | 
| +	      hash->root.u.def.value = filehdr_vaddr - s->vma;
 | 
| +	      hash->root.u.def.section = s;
 | 
| +	    }
 | 
| +	  else
 | 
| +	    {
 | 
| +	      hash->root.u.def.value = filehdr_vaddr;
 | 
| +	      hash->root.u.def.section = bfd_abs_section_ptr;
 | 
| +	    }
 | 
| +
 | 
| +	  hash->root.type = bfd_link_hash_defined;
 | 
| +	  hash->def_regular = 1;
 | 
| +	  hash->non_elf = 0;
 | 
| +	}
 | 
| +    }
 | 
| +
 | 
|    for (m = elf_tdata (abfd)->segment_map, p = phdrs;
 | 
|         m != NULL;
 | 
|         m = m->next, p++)
 | 
| @@ -4886,21 +4969,27 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
 | 
|        if (p->p_type == PT_GNU_RELRO)
 | 
|  	{
 | 
|  	  const Elf_Internal_Phdr *lp;
 | 
| -
 | 
| -	  BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs);
 | 
| +	  struct elf_segment_map *lm;
 | 
|  
 | 
|  	  if (link_info != NULL)
 | 
|  	    {
 | 
|  	      /* During linking the range of the RELRO segment is passed
 | 
|  		 in link_info.  */
 | 
| -	      for (lp = phdrs; lp < phdrs + count; ++lp)
 | 
| +	      for (lm = elf_tdata (abfd)->segment_map, lp = phdrs;
 | 
| +		   lm != NULL;
 | 
| +		   lm = lm->next, lp++)
 | 
|  		{
 | 
|  		  if (lp->p_type == PT_LOAD
 | 
| -		      && lp->p_vaddr >= link_info->relro_start
 | 
|  		      && lp->p_vaddr < link_info->relro_end
 | 
| -		      && lp->p_vaddr + lp->p_filesz >= link_info->relro_end)
 | 
| +		      && lp->p_vaddr + lp->p_filesz >= link_info->relro_end
 | 
| +		      && lm->count != 0
 | 
| +		      && lm->sections[0]->vma >= link_info->relro_start)
 | 
|  		    break;
 | 
|  		}
 | 
| +
 | 
| +	      /* PR ld/14207.  If the RELRO segment doesn't fit in the
 | 
| +		 LOAD segment, it should be removed.  */
 | 
| +	      BFD_ASSERT (lm != NULL);
 | 
|  	    }
 | 
|  	  else
 | 
|  	    {
 | 
| @@ -4926,8 +5015,15 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
 | 
|  	      else
 | 
|  		abort ();
 | 
|  	      p->p_memsz = p->p_filesz;
 | 
| -	      p->p_align = 1;
 | 
| -	      p->p_flags = (lp->p_flags & ~PF_W);
 | 
| +	      /* Preserve the alignment and flags if they are valid. The
 | 
| +	         gold linker generates RW/4 for the PT_GNU_RELRO section.
 | 
| +		 It is better for objcopy/strip to honor these attributes
 | 
| +		 otherwise gdb will choke when using separate debug files.
 | 
| +	       */
 | 
| +	      if (!m->p_align_valid)
 | 
| +		p->p_align = 1;
 | 
| +	      if (!m->p_flags_valid)
 | 
| +		p->p_flags = (lp->p_flags & ~PF_W);
 | 
|  	    }
 | 
|  	  else
 | 
|  	    {
 | 
| @@ -5427,7 +5523,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
 | 
|         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 section or a NOTE section in a PT_NOTE
 | 
| -	  segment.         
 | 
| +	  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.
 | 
| @@ -6147,7 +6243,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
 | 
|        if (map->includes_filehdr && lowest_section != NULL)
 | 
|  	/* We need to keep the space used by the headers fixed.  */
 | 
|  	map->header_size = lowest_section->vma - segment->p_vaddr;
 | 
| -      
 | 
| +
 | 
|        if (!map->includes_phdrs
 | 
|  	  && !map->includes_filehdr
 | 
|  	  && map->p_paddr_valid)
 | 
| @@ -7378,65 +7474,74 @@ elf_find_function (bfd *abfd,
 | 
|  		   const char **filename_ptr,
 | 
|  		   const char **functionname_ptr)
 | 
|  {
 | 
| -  const char *filename;
 | 
| -  asymbol *func, *file;
 | 
| -  bfd_vma low_func;
 | 
| -  asymbol **p;
 | 
| -  /* ??? Given multiple file symbols, it is impossible to reliably
 | 
| -     choose the right file name for global symbols.  File symbols are
 | 
| -     local symbols, and thus all file symbols must sort before any
 | 
| -     global symbols.  The ELF spec may be interpreted to say that a
 | 
| -     file symbol must sort before other local symbols, but currently
 | 
| -     ld -r doesn't do this.  So, for ld -r output, it is possible to
 | 
| -     make a better choice of file name for local symbols by ignoring
 | 
| -     file symbols appearing after a given local symbol.  */
 | 
| -  enum { nothing_seen, symbol_seen, file_after_symbol_seen } state;
 | 
| -  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 | 
| +  static asection *last_section;
 | 
| +  static asymbol *func;
 | 
| +  static const char *filename;
 | 
| +  static bfd_size_type func_size;
 | 
|  
 | 
|    if (symbols == NULL)
 | 
|      return FALSE;
 | 
|  
 | 
| -  filename = NULL;
 | 
| -  func = NULL;
 | 
| -  file = NULL;
 | 
| -  low_func = 0;
 | 
| -  state = nothing_seen;
 | 
| -
 | 
| -  for (p = symbols; *p != NULL; p++)
 | 
| -    {
 | 
| -      elf_symbol_type *q;
 | 
| -      unsigned int type;
 | 
| -
 | 
| -      q = (elf_symbol_type *) *p;
 | 
| +  if (last_section != section
 | 
| +      || func == NULL
 | 
| +      || offset < func->value
 | 
| +      || offset >= func->value + func_size)
 | 
| +    {
 | 
| +      asymbol *file;
 | 
| +      bfd_vma low_func;
 | 
| +      asymbol **p;
 | 
| +      /* ??? Given multiple file symbols, it is impossible to reliably
 | 
| +	 choose the right file name for global symbols.  File symbols are
 | 
| +	 local symbols, and thus all file symbols must sort before any
 | 
| +	 global symbols.  The ELF spec may be interpreted to say that a
 | 
| +	 file symbol must sort before other local symbols, but currently
 | 
| +	 ld -r doesn't do this.  So, for ld -r output, it is possible to
 | 
| +	 make a better choice of file name for local symbols by ignoring
 | 
| +	 file symbols appearing after a given local symbol.  */
 | 
| +      enum { nothing_seen, symbol_seen, file_after_symbol_seen } state;
 | 
| +      const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 | 
| +
 | 
| +      filename = NULL;
 | 
| +      func = NULL;
 | 
| +      file = NULL;
 | 
| +      low_func = 0;
 | 
| +      state = nothing_seen;
 | 
| +      func_size = 0;
 | 
| +      last_section = section;
 | 
| +
 | 
| +      for (p = symbols; *p != NULL; p++)
 | 
| +	{
 | 
| +	  asymbol *sym = *p;
 | 
| +	  bfd_vma code_off;
 | 
| +	  bfd_size_type size;
 | 
| +
 | 
| +	  if ((sym->flags & BSF_FILE) != 0)
 | 
| +	    {
 | 
| +	      file = sym;
 | 
| +	      if (state == symbol_seen)
 | 
| +		state = file_after_symbol_seen;
 | 
| +	      continue;
 | 
| +	    }
 | 
|  
 | 
| -      type = ELF_ST_TYPE (q->internal_elf_sym.st_info);
 | 
| -      switch (type)
 | 
| -	{
 | 
| -	case STT_FILE:
 | 
| -	  file = &q->symbol;
 | 
| -	  if (state == symbol_seen)
 | 
| -	    state = file_after_symbol_seen;
 | 
| -	  continue;
 | 
| -	default:
 | 
| -	  if (!bed->is_function_type (type))
 | 
| -	    break;
 | 
| -	case STT_NOTYPE:
 | 
| -	  if (bfd_get_section (&q->symbol) == section
 | 
| -	      && q->symbol.value >= low_func
 | 
| -	      && q->symbol.value <= offset)
 | 
| +	  size = bed->maybe_function_sym (sym, section, &code_off);
 | 
| +	  if (size != 0
 | 
| +	      && code_off <= offset
 | 
| +	      && (code_off > low_func
 | 
| +		  || (code_off == low_func
 | 
| +		      && size > func_size)))
 | 
|  	    {
 | 
| -	      func = (asymbol *) q;
 | 
| -	      low_func = q->symbol.value;
 | 
| +	      func = sym;
 | 
| +	      func_size = size;
 | 
| +	      low_func = code_off;
 | 
|  	      filename = NULL;
 | 
|  	      if (file != NULL
 | 
| -		  && (ELF_ST_BIND (q->internal_elf_sym.st_info) == STB_LOCAL
 | 
| +		  && ((sym->flags & BSF_LOCAL) != 0
 | 
|  		      || state != file_after_symbol_seen))
 | 
|  		filename = bfd_asymbol_name (file);
 | 
|  	    }
 | 
| -	  break;
 | 
| +	  if (state == nothing_seen)
 | 
| +	    state = symbol_seen;
 | 
|  	}
 | 
| -      if (state == nothing_seen)
 | 
| -	state = symbol_seen;
 | 
|      }
 | 
|  
 | 
|    if (func == NULL)
 | 
| @@ -7698,11 +7803,12 @@ _bfd_elf_validate_reloc (bfd *abfd, arelent *areloc)
 | 
|  bfd_boolean
 | 
|  _bfd_elf_close_and_cleanup (bfd *abfd)
 | 
|  {
 | 
| -  if (bfd_get_format (abfd) == bfd_object)
 | 
| +  struct elf_obj_tdata *tdata = elf_tdata (abfd);
 | 
| +  if (bfd_get_format (abfd) == bfd_object && tdata != NULL)
 | 
|      {
 | 
| -      if (elf_tdata (abfd) != NULL && elf_shstrtab (abfd) != NULL)
 | 
| +      if (elf_shstrtab (abfd) != NULL)
 | 
|  	_bfd_elf_strtab_free (elf_shstrtab (abfd));
 | 
| -      _bfd_dwarf2_cleanup_debug_info (abfd);
 | 
| +      _bfd_dwarf2_cleanup_debug_info (abfd, &tdata->dwarf2_find_line_info);
 | 
|      }
 | 
|  
 | 
|    return _bfd_generic_close_and_cleanup (abfd);
 | 
| @@ -8889,7 +8995,6 @@ elfcore_write_note (bfd *abfd,
 | 
|    return buf;
 | 
|  }
 | 
|  
 | 
| -#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
 | 
|  char *
 | 
|  elfcore_write_prpsinfo (bfd  *abfd,
 | 
|  			char *buf,
 | 
| @@ -8897,7 +9002,6 @@ elfcore_write_prpsinfo (bfd  *abfd,
 | 
|  			const char *fname,
 | 
|  			const char *psargs)
 | 
|  {
 | 
| -  const char *note_name = "CORE";
 | 
|    const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 | 
|  
 | 
|    if (bed->elf_backend_write_core_note != NULL)
 | 
| @@ -8909,6 +9013,7 @@ elfcore_write_prpsinfo (bfd  *abfd,
 | 
|  	return ret;
 | 
|      }
 | 
|  
 | 
| +#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
 | 
|  #if defined (HAVE_PRPSINFO32_T) || defined (HAVE_PSINFO32_T)
 | 
|    if (bed->s->elfclass == ELFCLASS32)
 | 
|      {
 | 
| @@ -8924,7 +9029,7 @@ elfcore_write_prpsinfo (bfd  *abfd,
 | 
|        strncpy (data.pr_fname, fname, sizeof (data.pr_fname));
 | 
|        strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs));
 | 
|        return elfcore_write_note (abfd, buf, bufsiz,
 | 
| -				 note_name, note_type, &data, sizeof (data));
 | 
| +				 "CORE", note_type, &data, sizeof (data));
 | 
|      }
 | 
|    else
 | 
|  #endif
 | 
| @@ -8941,12 +9046,14 @@ elfcore_write_prpsinfo (bfd  *abfd,
 | 
|        strncpy (data.pr_fname, fname, sizeof (data.pr_fname));
 | 
|        strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs));
 | 
|        return elfcore_write_note (abfd, buf, bufsiz,
 | 
| -				 note_name, note_type, &data, sizeof (data));
 | 
| +				 "CORE", note_type, &data, sizeof (data));
 | 
|      }
 | 
| -}
 | 
|  #endif	/* PSINFO_T or PRPSINFO_T */
 | 
|  
 | 
| -#if defined (HAVE_PRSTATUS_T)
 | 
| +  free (buf);
 | 
| +  return NULL;
 | 
| +}
 | 
| +
 | 
|  char *
 | 
|  elfcore_write_prstatus (bfd *abfd,
 | 
|  			char *buf,
 | 
| @@ -8955,7 +9062,6 @@ elfcore_write_prstatus (bfd *abfd,
 | 
|  			int cursig,
 | 
|  			const void *gregs)
 | 
|  {
 | 
| -  const char *note_name = "CORE";
 | 
|    const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 | 
|  
 | 
|    if (bed->elf_backend_write_core_note != NULL)
 | 
| @@ -8968,6 +9074,7 @@ elfcore_write_prstatus (bfd *abfd,
 | 
|  	return ret;
 | 
|      }
 | 
|  
 | 
| +#if defined (HAVE_PRSTATUS_T)
 | 
|  #if defined (HAVE_PRSTATUS32_T)
 | 
|    if (bed->s->elfclass == ELFCLASS32)
 | 
|      {
 | 
| @@ -8977,7 +9084,7 @@ elfcore_write_prstatus (bfd *abfd,
 | 
|        prstat.pr_pid = pid;
 | 
|        prstat.pr_cursig = cursig;
 | 
|        memcpy (&prstat.pr_reg, gregs, sizeof (prstat.pr_reg));
 | 
| -      return elfcore_write_note (abfd, buf, bufsiz, note_name,
 | 
| +      return elfcore_write_note (abfd, buf, bufsiz, "CORE",
 | 
|  				 NT_PRSTATUS, &prstat, sizeof (prstat));
 | 
|      }
 | 
|    else
 | 
| @@ -8989,12 +9096,15 @@ elfcore_write_prstatus (bfd *abfd,
 | 
|        prstat.pr_pid = pid;
 | 
|        prstat.pr_cursig = cursig;
 | 
|        memcpy (&prstat.pr_reg, gregs, sizeof (prstat.pr_reg));
 | 
| -      return elfcore_write_note (abfd, buf, bufsiz, note_name,
 | 
| +      return elfcore_write_note (abfd, buf, bufsiz, "CORE",
 | 
|  				 NT_PRSTATUS, &prstat, sizeof (prstat));
 | 
|      }
 | 
| -}
 | 
|  #endif /* HAVE_PRSTATUS_T */
 | 
|  
 | 
| +  free (buf);
 | 
| +  return NULL;
 | 
| +}
 | 
| +
 | 
|  #if defined (HAVE_LWPSTATUS_T)
 | 
|  char *
 | 
|  elfcore_write_lwpstatus (bfd *abfd,
 | 
| @@ -9447,7 +9557,7 @@ _bfd_elf_rela_local_sym (bfd *abfd,
 | 
|  		+ sym->st_value);
 | 
|    if ((sec->flags & SEC_MERGE)
 | 
|        && ELF_ST_TYPE (sym->st_info) == STT_SECTION
 | 
| -      && sec->sec_info_type == ELF_INFO_TYPE_MERGE)
 | 
| +      && sec->sec_info_type == SEC_INFO_TYPE_MERGE)
 | 
|      {
 | 
|        rel->r_addend =
 | 
|  	_bfd_merged_section_offset (abfd, psec,
 | 
| @@ -9478,7 +9588,7 @@ _bfd_elf_rel_local_sym (bfd *abfd,
 | 
|  {
 | 
|    asection *sec = *psec;
 | 
|  
 | 
| -  if (sec->sec_info_type != ELF_INFO_TYPE_MERGE)
 | 
| +  if (sec->sec_info_type != SEC_INFO_TYPE_MERGE)
 | 
|      return sym->st_value + addend;
 | 
|  
 | 
|    return _bfd_merged_section_offset (abfd, psec,
 | 
| @@ -9494,10 +9604,10 @@ _bfd_elf_section_offset (bfd *abfd,
 | 
|  {
 | 
|    switch (sec->sec_info_type)
 | 
|      {
 | 
| -    case ELF_INFO_TYPE_STABS:
 | 
| +    case SEC_INFO_TYPE_STABS:
 | 
|        return _bfd_stab_section_offset (sec, elf_section_data (sec)->sec_info,
 | 
|  				       offset);
 | 
| -    case ELF_INFO_TYPE_EH_FRAME:
 | 
| +    case SEC_INFO_TYPE_EH_FRAME:
 | 
|        return _bfd_elf_eh_frame_section_offset (abfd, info, sec, offset);
 | 
|      default:
 | 
|        if ((sec->flags & SEC_ELF_REVERSE_COPY) != 0)
 | 
| @@ -9528,7 +9638,7 @@ bfd_elf_bfd_from_remote_memory
 | 
|    (bfd *templ,
 | 
|     bfd_vma ehdr_vma,
 | 
|     bfd_vma *loadbasep,
 | 
| -   int (*target_read_memory) (bfd_vma, bfd_byte *, int))
 | 
| +   int (*target_read_memory) (bfd_vma, bfd_byte *, bfd_size_type))
 | 
|  {
 | 
|    return (*get_elf_backend_data (templ)->elf_backend_bfd_from_remote_memory)
 | 
|      (templ, ehdr_vma, loadbasep, target_read_memory);
 | 
| @@ -9633,7 +9743,7 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd,
 | 
|        if (p->addend != 0)
 | 
|  	{
 | 
|  	  char buf[30], *a;
 | 
| -	  
 | 
| +
 | 
|  	  memcpy (names, "+0x", sizeof ("+0x") - 1);
 | 
|  	  names += sizeof ("+0x") - 1;
 | 
|  	  bfd_sprintf_vma (abfd, buf, p->addend);
 | 
| @@ -9685,3 +9795,27 @@ _bfd_elf_is_function_type (unsigned int type)
 | 
|    return (type == STT_FUNC
 | 
|  	  || type == STT_GNU_IFUNC);
 | 
|  }
 | 
| +
 | 
| +/* If the ELF symbol SYM might be a function in SEC, return the
 | 
| +   function size and set *CODE_OFF to the function's entry point,
 | 
| +   otherwise return zero.  */
 | 
| +
 | 
| +bfd_size_type
 | 
| +_bfd_elf_maybe_function_sym (const asymbol *sym, asection *sec,
 | 
| +			     bfd_vma *code_off)
 | 
| +{
 | 
| +  bfd_size_type size;
 | 
| +
 | 
| +  if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT
 | 
| +		     | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0
 | 
| +      || sym->section != sec)
 | 
| +    return 0;
 | 
| +
 | 
| +  *code_off = sym->value;
 | 
| +  size = 0;
 | 
| +  if (!(sym->flags & BSF_SYNTHETIC))
 | 
| +    size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
 | 
| +  if (size == 0)
 | 
| +    size = 1;
 | 
| +  return size;
 | 
| +}
 | 
| 
 |