FreeBSD/contrib/binutils/bfd/elf.c
/* Make a BFD section from an ELF section.  We store a pointer to the
   BFD section in the bfd_section field of the header.  */
Make a BFD section from an ELF section.  We store a pointer to the
BFD section in the bfd_section field of the header.
Make a BFD section from an ELF section . We store a pointer to the BFD section in the bfd_section field of the header .
bfd_boolean
_bfd_elf_make_section_from_shdr (bfd *abfd,
				 Elf_Internal_Shdr *hdr,
				 const char *name,
				 int shindex)
{
  asection *newsect;
  flagword flags;
  const struct elf_backend_data *bed;
  if (hdr->bfd_section != NULL)
    {
      BFD_ASSERT (strcmp (name,
			  bfd_get_section_name (abfd, hdr->bfd_section)) == 0);
      return TRUE;
    }
  newsect = bfd_make_section_anyway (abfd, name);
  if (newsect == NULL)
    return FALSE;
  hdr->bfd_section = newsect;
  elf_section_data (newsect)->this_hdr = *hdr;
  elf_section_data (newsect)->this_idx = shindex;
  elf_section_type (newsect) = hdr->sh_type;
  elf_section_flags (newsect) = hdr->sh_flags;
  newsect->filepos = hdr->sh_offset;
  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)))
    return FALSE;
  flags = SEC_NO_FLAGS;
  if (hdr->sh_type != SHT_NOBITS)
    flags |= SEC_HAS_CONTENTS;
  if (hdr->sh_type == SHT_GROUP)
    flags |= SEC_GROUP | SEC_EXCLUDE;
  if ((hdr->sh_flags & SHF_ALLOC) != 0)
    {
      flags |= SEC_ALLOC;
      if (hdr->sh_type != SHT_NOBITS)
	flags |= SEC_LOAD;
    }
  if ((hdr->sh_flags & SHF_WRITE) == 0)
    flags |= SEC_READONLY;
  if ((hdr->sh_flags & SHF_EXECINSTR) != 0)
    flags |= SEC_CODE;
  else if ((flags & SEC_LOAD) != 0)
    flags |= SEC_DATA;
  if ((hdr->sh_flags & SHF_MERGE) != 0)
    {
      flags |= SEC_MERGE;
      newsect->entsize = hdr->sh_entsize;
      if ((hdr->sh_flags & SHF_STRINGS) != 0)
	flags |= SEC_STRINGS;
    }
  if (hdr->sh_flags & SHF_GROUP)
    if (!setup_group (abfd, hdr, newsect))
      return FALSE;
  if ((hdr->sh_flags & SHF_TLS) != 0)
    flags |= SEC_THREAD_LOCAL;
  if ((flags & SEC_ALLOC) == 0)
    {
      static const struct
	{
	  const char *name;
	  int len;
	} debug_sections [] =
	{
	  { STRING_COMMA_LEN ("debug") },	
	  { NULL,		 0  },	
	  { NULL,		 0  },	
	  { STRING_COMMA_LEN ("gnu.linkonce.wi.") },	
	  { NULL,		 0  },	
	  { NULL,		 0  },	
	  { NULL,		 0  },	
	  { NULL,		 0  },	
	  { STRING_COMMA_LEN ("line") },	
	  { NULL,		 0  },	
	  { NULL,		 0  },	
	  { NULL,		 0  },	
	  { NULL,		 0  },	
	  { NULL,		 0  },	
	  { NULL,		 0  },	
	  { STRING_COMMA_LEN ("stab") }	
	};
      if (name [0] == '.')
	{
	  int i = name [1] - 'd';
	  if (i >= 0
	      && i < (int) ARRAY_SIZE (debug_sections)
	      && debug_sections [i].name != NULL
	      && strncmp (&name [1], debug_sections [i].name,
			  debug_sections [i].len) == 0)
	    flags |= SEC_DEBUGGING;
	}
    }
  if (CONST_STRNEQ (name, ".gnu.linkonce")
      && elf_next_in_group (newsect) == NULL)
    flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
  bed = get_elf_backend_data (abfd);
  if (bed->elf_backend_section_flags)
    if (! bed->elf_backend_section_flags (&flags, hdr))
      return FALSE;
  if (! bfd_set_section_flags (abfd, newsect, flags))
    return FALSE;
  if ((flags & SEC_ALLOC) != 0)
    {
      Elf_Internal_Phdr *phdr;
      unsigned int i;
      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++)
	    {
	      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
		    newsect->lma = (phdr->p_paddr
				    + hdr->sh_offset - phdr->p_offset);
		  if (hdr->sh_addr >= phdr->p_vaddr
		      && (hdr->sh_addr + hdr->sh_size
			  <= phdr->p_vaddr + phdr->p_memsz))
		    break;
		}
	    }
	}
    }
  return TRUE;
}
bfd_boolean _bfd_elf_make_section_from_shdr ( bfd * abfd , Elf_Internal_Shdr * hdr , const char * name , int shindex ) { asection * newsect ; flagword flags ; const struct elf_backend_data * bed ; if ( hdr -> bfd_section != NULL ) { BFD_ASSERT ( strcmp ( name , bfd_get_section_name ( abfd , hdr -> bfd_section ) ) == 0 ) ; return TRUE ; } newsect = bfd_make_section_anyway ( abfd , name ) ; if ( newsect == NULL ) return FALSE ; hdr -> bfd_section = newsect ; elf_section_data ( newsect ) -> this_hdr = * hdr ; elf_section_data ( newsect ) -> this_idx = shindex ; elf_section_type ( newsect ) = hdr -> sh_type ; elf_section_flags ( newsect ) = hdr -> sh_flags ; newsect -> filepos = hdr -> sh_offset ; 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 ) ) ) return FALSE ; flags = SEC_NO_FLAGS ; if ( hdr -> sh_type != SHT_NOBITS ) flags |= SEC_HAS_CONTENTS ; if ( hdr -> sh_type == SHT_GROUP ) flags |= SEC_GROUP | SEC_EXCLUDE ; if ( ( hdr -> sh_flags & SHF_ALLOC ) != 0 ) { flags |= SEC_ALLOC ; if ( hdr -> sh_type != SHT_NOBITS ) flags |= SEC_LOAD ; } if ( ( hdr -> sh_flags & SHF_WRITE ) == 0 ) flags |= SEC_READONLY ; if ( ( hdr -> sh_flags & SHF_EXECINSTR ) != 0 ) flags |= SEC_CODE ; else if ( ( flags & SEC_LOAD ) != 0 ) flags |= SEC_DATA ; if ( ( hdr -> sh_flags & SHF_MERGE ) != 0 ) { flags |= SEC_MERGE ; newsect -> entsize = hdr -> sh_entsize ; if ( ( hdr -> sh_flags & SHF_STRINGS ) != 0 ) flags |= SEC_STRINGS ; } if ( hdr -> sh_flags & SHF_GROUP ) if ( ! setup_group ( abfd , hdr , newsect ) ) return FALSE ; if ( ( hdr -> sh_flags & SHF_TLS ) != 0 ) flags |= SEC_THREAD_LOCAL ; if ( ( flags & SEC_ALLOC ) == 0 ) { static const struct { const char * name ; int len ; } debug_sections [ ] = { { STRING_COMMA_LEN ( " " ) } , { NULL , 0 } , { NULL , 0 } , { STRING_COMMA_LEN ( " " ) } , { NULL , 0 } , { NULL , 0 } , { NULL , 0 } , { NULL , 0 } , { STRING_COMMA_LEN ( " " ) } , { NULL , 0 } , { NULL , 0 } , { NULL , 0 } , { NULL , 0 } , { NULL , 0 } , { NULL , 0 } , { STRING_COMMA_LEN ( " " ) } } ; if ( name [ 0 ] == ' ' ) { int i = name [ 1 ] - ' ' ; if ( i >= 0 && i < ( int ) ARRAY_SIZE ( debug_sections ) && debug_sections [ i ] . name != NULL && strncmp ( & name [ 1 ] , debug_sections [ i ] . name , debug_sections [ i ] . len ) == 0 ) flags |= SEC_DEBUGGING ; } } if ( CONST_STRNEQ ( name , " " ) && elf_next_in_group ( newsect ) == NULL ) flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD ; bed = get_elf_backend_data ( abfd ) ; if ( bed -> elf_backend_section_flags ) if ( ! bed -> elf_backend_section_flags ( & flags , hdr ) ) return FALSE ; if ( ! bfd_set_section_flags ( abfd , newsect , flags ) ) return FALSE ; if ( ( flags & SEC_ALLOC ) != 0 ) { Elf_Internal_Phdr * phdr ; unsigned int i ; 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 ++ ) { 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 newsect -> lma = ( phdr -> p_paddr + hdr -> sh_offset - phdr -> p_offset ) ; if ( hdr -> sh_addr >= phdr -> p_vaddr && ( hdr -> sh_addr + hdr -> sh_size <= phdr -> p_vaddr + phdr -> p_memsz ) ) break ; } } } } return TRUE ; }
Make a BFD section from an ELF section.
Make a BFD section from an ELF section .
/* Always use the real type/flags.  */ /* The debugging sections appear to be recognized only by name,
	 not any sort of flag.  Their SEC_ALLOC bits are cleared.  */ /* 'd' */ /* 'e' */ /* 'f' */ /* 'g' */ /* 'h' */ /* 'i' */ /* 'j' */ /* 'k' */ /* 'l' */ /* 'm' */ /* 'n' */ /* 'o' */ /* 'p' */ /* 'q' */ /* 'r' */ /* 's' */ /* As a GNU extension, if the name begins with .gnu.linkonce, we
     only link a single copy of the section.  This is used to support
     g++.  g++ will emit each template expansion in its own section.
     The symbols will be defined as weak, so that multiple definitions
     are permitted.  The GNU linker extension is to actually discard
     all but one of the sections.  */ /* 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.  */ /* 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.  */ /* 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.  */ /* 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.  */