FreeBSD/contrib/binutils/bfd/elf.c
/* Assign file positions for the other sections.  */
Assign file positions for the other sections.
Assign file positions for the other sections .
static bfd_boolean
assign_file_positions_for_non_load_sections (bfd *abfd,
					     struct bfd_link_info *link_info)
{
  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
  Elf_Internal_Shdr **i_shdrpp;
  Elf_Internal_Shdr **hdrpp;
  Elf_Internal_Phdr *phdrs;
  Elf_Internal_Phdr *p;
  struct elf_segment_map *m;
  bfd_vma filehdr_vaddr, filehdr_paddr;
  bfd_vma phdrs_vaddr, phdrs_paddr;
  file_ptr off;
  unsigned int num_sec;
  unsigned int i;
  unsigned int count;
  i_shdrpp = elf_elfsections (abfd);
  num_sec = elf_numsections (abfd);
  off = elf_tdata (abfd)->next_file_pos;
  for (i = 1, hdrpp = i_shdrpp + 1; i < num_sec; i++, hdrpp++)
    {
      struct elf_obj_tdata *tdata = elf_tdata (abfd);
      Elf_Internal_Shdr *hdr;
      hdr = *hdrpp;
      if (hdr->bfd_section != NULL
	  && (hdr->bfd_section->filepos != 0
	      || (hdr->sh_type == SHT_NOBITS
		  && hdr->contents == NULL)))
	BFD_ASSERT (hdr->sh_offset == hdr->bfd_section->filepos);
      else if ((hdr->sh_flags & SHF_ALLOC) != 0)
	{
	  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)));
	  if ((abfd->flags & D_PAGED) != 0 && hdr->sh_size != 0)
	    off += vma_page_aligned_bias (hdr->sh_addr, off,
					  bed->maxpagesize);
	  else
	    off += vma_page_aligned_bias (hdr->sh_addr, off,
					  hdr->sh_addralign);
	  off = _bfd_elf_assign_file_position_for_section (hdr, off,
							   FALSE);
	}
      else if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
		&& hdr->bfd_section == NULL)
	       || 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;
	}
    }
  count = 0;
  filehdr_vaddr = 0;
  filehdr_paddr = 0;
  phdrs_vaddr = bed->maxpagesize + bed->s->sizeof_ehdr;
  phdrs_paddr = 0;
  phdrs = elf_tdata (abfd)->phdr;
  for (m = elf_tdata (abfd)->segment_map, p = phdrs;
       m != NULL;
       m = m->next, p++)
    {
      ++count;
      if (p->p_type != PT_LOAD)
	continue;
      if (m->includes_filehdr)
	{
	  filehdr_vaddr = p->p_vaddr;
	  filehdr_paddr = p->p_paddr;
	}
      if (m->includes_phdrs)
	{
	  phdrs_vaddr = p->p_vaddr;
	  phdrs_paddr = p->p_paddr;
	  if (m->includes_filehdr)
	    {
	      phdrs_vaddr += bed->s->sizeof_ehdr;
	      phdrs_paddr += bed->s->sizeof_ehdr;
	    }
	}
    }
  for (m = elf_tdata (abfd)->segment_map, p = phdrs;
       m != NULL;
       m = m->next, p++)
    {
      if (m->count != 0)
	{
	  if (p->p_type != PT_LOAD
	      && (p->p_type != PT_NOTE || bfd_get_format (abfd) != bfd_core))
	    {
	      Elf_Internal_Shdr *hdr;
	      BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs);
	      hdr = &elf_section_data (m->sections[m->count - 1])->this_hdr;
	      p->p_filesz = (m->sections[m->count - 1]->filepos
			     - m->sections[0]->filepos);
	      if (hdr->sh_type != SHT_NOBITS)
		p->p_filesz += hdr->sh_size;
	      p->p_offset = m->sections[0]->filepos;
	    }
	}
      else
	{
	  if (m->includes_filehdr)
	    {
	      p->p_vaddr = filehdr_vaddr;
	      if (! m->p_paddr_valid)
		p->p_paddr = filehdr_paddr;
	    }
	  else if (m->includes_phdrs)
	    {
	      p->p_vaddr = phdrs_vaddr;
	      if (! m->p_paddr_valid)
		p->p_paddr = phdrs_paddr;
	    }
	  else if (p->p_type == PT_GNU_RELRO)
	    {
	      Elf_Internal_Phdr *lp;
	      for (lp = phdrs; lp < phdrs + count; ++lp)
		{
		  if (lp->p_type == PT_LOAD
		      && lp->p_vaddr <= link_info->relro_end
		      && lp->p_vaddr >= link_info->relro_start
		      && (lp->p_vaddr + lp->p_filesz
			  >= link_info->relro_end))
		    break;
		}
	      if (lp < phdrs + count
		  && link_info->relro_end > lp->p_vaddr)
		{
		  p->p_vaddr = lp->p_vaddr;
		  p->p_paddr = lp->p_paddr;
		  p->p_offset = lp->p_offset;
		  p->p_filesz = link_info->relro_end - lp->p_vaddr;
		  p->p_memsz = p->p_filesz;
		  p->p_align = 1;
		  p->p_flags = (lp->p_flags & ~PF_W);
		}
	      else
		{
		  memset (p, 0, sizeof *p);
		  p->p_type = PT_NULL;
		}
	    }
	}
    }
  elf_tdata (abfd)->next_file_pos = off;
  return TRUE;
}
static bfd_boolean assign_file_positions_for_non_load_sections ( bfd * abfd , struct bfd_link_info * link_info ) { const struct elf_backend_data * bed = get_elf_backend_data ( abfd ) ; Elf_Internal_Shdr * * i_shdrpp ; Elf_Internal_Shdr * * hdrpp ; Elf_Internal_Phdr * phdrs ; Elf_Internal_Phdr * p ; struct elf_segment_map * m ; bfd_vma filehdr_vaddr , filehdr_paddr ; bfd_vma phdrs_vaddr , phdrs_paddr ; file_ptr off ; unsigned int num_sec ; unsigned int i ; unsigned int count ; i_shdrpp = elf_elfsections ( abfd ) ; num_sec = elf_numsections ( abfd ) ; off = elf_tdata ( abfd ) -> next_file_pos ; for ( i = 1 , hdrpp = i_shdrpp + 1 ; i < num_sec ; i ++ , hdrpp ++ ) { struct elf_obj_tdata * tdata = elf_tdata ( abfd ) ; Elf_Internal_Shdr * hdr ; hdr = * hdrpp ; if ( hdr -> bfd_section != NULL && ( hdr -> bfd_section -> filepos != 0 || ( hdr -> sh_type == SHT_NOBITS && hdr -> contents == NULL ) ) ) BFD_ASSERT ( hdr -> sh_offset == hdr -> bfd_section -> filepos ) ; else if ( ( hdr -> sh_flags & SHF_ALLOC ) != 0 ) { if ( hdr -> sh_size != 0 ) ( ( * _bfd_error_handler ) ( _ ( " " ) , abfd , ( hdr -> bfd_section == NULL ? " " : hdr -> bfd_section -> name ) ) ) ; if ( ( abfd -> flags & D_PAGED ) != 0 && hdr -> sh_size != 0 ) off += vma_page_aligned_bias ( hdr -> sh_addr , off , bed -> maxpagesize ) ; else off += vma_page_aligned_bias ( hdr -> sh_addr , off , hdr -> sh_addralign ) ; off = _bfd_elf_assign_file_position_for_section ( hdr , off , FALSE ) ; } else if ( ( ( hdr -> sh_type == SHT_REL || hdr -> sh_type == SHT_RELA ) && hdr -> bfd_section == NULL ) || 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 ; } } count = 0 ; filehdr_vaddr = 0 ; filehdr_paddr = 0 ; phdrs_vaddr = bed -> maxpagesize + bed -> s -> sizeof_ehdr ; phdrs_paddr = 0 ; phdrs = elf_tdata ( abfd ) -> phdr ; for ( m = elf_tdata ( abfd ) -> segment_map , p = phdrs ; m != NULL ; m = m -> next , p ++ ) { ++ count ; if ( p -> p_type != PT_LOAD ) continue ; if ( m -> includes_filehdr ) { filehdr_vaddr = p -> p_vaddr ; filehdr_paddr = p -> p_paddr ; } if ( m -> includes_phdrs ) { phdrs_vaddr = p -> p_vaddr ; phdrs_paddr = p -> p_paddr ; if ( m -> includes_filehdr ) { phdrs_vaddr += bed -> s -> sizeof_ehdr ; phdrs_paddr += bed -> s -> sizeof_ehdr ; } } } for ( m = elf_tdata ( abfd ) -> segment_map , p = phdrs ; m != NULL ; m = m -> next , p ++ ) { if ( m -> count != 0 ) { if ( p -> p_type != PT_LOAD && ( p -> p_type != PT_NOTE || bfd_get_format ( abfd ) != bfd_core ) ) { Elf_Internal_Shdr * hdr ; BFD_ASSERT ( ! m -> includes_filehdr && ! m -> includes_phdrs ) ; hdr = & elf_section_data ( m -> sections [ m -> count - 1 ] ) -> this_hdr ; p -> p_filesz = ( m -> sections [ m -> count - 1 ] -> filepos - m -> sections [ 0 ] -> filepos ) ; if ( hdr -> sh_type != SHT_NOBITS ) p -> p_filesz += hdr -> sh_size ; p -> p_offset = m -> sections [ 0 ] -> filepos ; } } else { if ( m -> includes_filehdr ) { p -> p_vaddr = filehdr_vaddr ; if ( ! m -> p_paddr_valid ) p -> p_paddr = filehdr_paddr ; } else if ( m -> includes_phdrs ) { p -> p_vaddr = phdrs_vaddr ; if ( ! m -> p_paddr_valid ) p -> p_paddr = phdrs_paddr ; } else if ( p -> p_type == PT_GNU_RELRO ) { Elf_Internal_Phdr * lp ; for ( lp = phdrs ; lp < phdrs + count ; ++ lp ) { if ( lp -> p_type == PT_LOAD && lp -> p_vaddr <= link_info -> relro_end && lp -> p_vaddr >= link_info -> relro_start && ( lp -> p_vaddr + lp -> p_filesz >= link_info -> relro_end ) ) break ; } if ( lp < phdrs + count && link_info -> relro_end > lp -> p_vaddr ) { p -> p_vaddr = lp -> p_vaddr ; p -> p_paddr = lp -> p_paddr ; p -> p_offset = lp -> p_offset ; p -> p_filesz = link_info -> relro_end - lp -> p_vaddr ; p -> p_memsz = p -> p_filesz ; p -> p_align = 1 ; p -> p_flags = ( lp -> p_flags & ~ PF_W ) ; } else { memset ( p , 0 , sizeof * p ) ; p -> p_type = PT_NULL ; } } } } elf_tdata ( abfd ) -> next_file_pos = off ; return TRUE ; }
Assign file positions for the other sections.
Assign file positions for the other sections .
/* We don't need to page align empty sections.  */ /* Now that we have set the section file positions, we can set up
     the file positions for the non PT_LOAD segments.  */