[PATCH v2] Fix several mix up between octets and bytes in ELF program headers

Christian Eggers ceggers@gmx.de
Tue Dec 17 20:45:00 GMT 2019


Hi Alan,

ping.... Seems you currently have some fun with ubsan.

regards
Christian


Am Montag, 9. Dezember 2019, 09:46:45 CET schrieb Christian Eggers:
> Alan Moda wrote:
> > I'm wondering if you would be better off leaving all the values as
> > octets when written to file.  There are things in the ELF spec, like
> > p_offset mod pagesize == p_vaddr mod pagesize, that assume p_offset
> > and p_vaddr have the same units.
>
> in v2 I've "kept" p_paddr, p_vaddr and sh_addr as octets. Compared to
> v1, the result is also ok for me. I had to disable one unit test for SDMA as
> 'objcopy --set-section-address .text=0x80000000' will overflow when
> converting 0x80000000 (LMA, bytes) to sh_addr (octets).
>
> ---
>
> When converting between addresses in ELF headers [octets] and bfd
> LMA/VMA [bytes], the number of octets per byte needs to be incorperated.
>
> In ld, the SIZEOF_HEADERS linker script statement must be resolved to
> bytes instead of octets.
>
> Patch changelog:
> v2: Keep ELF header entries as octets.
>
>
> include/
> 	* elf/internal.h (struct elf_internal_phdr): Add unit (octets)
> 	to several member field comments.
> 	(Elf_Internal_Shdr): likewise.
>
> bfd/
> 	* elf.c (_bfd_elf_make_section_from_shdr): Introduce new temp
> 	opb. Divide Elf_Internal_Shdr::sh_addr by opb when setting
> 	section LMA/VMA.
> 	(_bfd_elf_make_section_from_phdr): Similarly.
> 	(elf_fake_sections): Fix calculation of
> 	Elf_Internal_shdr::sh_addr from section VMA.
> 	(_bfd_elf_map_sections_to_segments): Fix mixup between octets
> 	and bytes.
> 	(assign_file_positions_for_load_sections): Fix calculations of
> 	Elf_Internal_shdr::p_vaddr and p_paddr from section LMA/VMA. Fix
> 	comparison between program header address and section LMA.
> 	(assign_file_positions_for_non_load_sections): Likewise.
> 	(rewrite_elf_program_header): Likewise. Introduce new temp opb.
> 	(IS_CONTAINED_BY_VMA): Add parameter opb.
> 	(IS_CONTAINED_BY_LMA,IS_SECTION_IN_INPUT_SEGMENT,
> 	INCLUDE_SECTION_IN_SEGMENT): Likewise.
> 	(copy_elf_program_header): Update call to
> 	ELF_SECTION_IN_SEGMENT(). Fix calculations of p_addr_valid and
> 	p_vaddr_offset.
> 	* elf32-rx.c (OCTETS_PER_BYTE): Define.
> 	(rx_elf_object_p): Use OCTETS_PER_BYTE for calculating
> 	section LMA from program header addresses.
> 	* elf64-ia64-vms.c (OCTETS_PER_BYTE): Define.
> 	(elf64_vms_link_add_object_symbols): Use OCTETS_PER_BYTE for
> 	calculating section LMA from program header addresses.
> 	* elflink.c (elf_link_add_object_symbols): Multiply section VMA
> 	with octets per byte when comparing against p_vaddr.
>
> ld/
> 	* ldexp.c (fold_name): Return SIZEOF_HEADERS in bytes.
>
> Signed-off-by: Christian Eggers <ceggers@gmx.de>
> ---
>  bfd/elf.c              | 131
> ++++++++++++++++++++++++++++--------------------- bfd/elf32-rx.c         |
>  8 ++-
>  bfd/elf64-ia64-vms.c   |   7 ++-
>  bfd/elflink.c          |  14 ++++--
>  include/elf/internal.h |  19 +++----
>  ld/ldexp.c             |   3 +-
>  6 files changed, 108 insertions(+), 74 deletions(-)
>
> diff --git a/bfd/elf.c b/bfd/elf.c
> index 1aa2603ee8c..d98cf9b8a51 100644
> --- a/bfd/elf.c
> +++ b/bfd/elf.c
> @@ -1028,6 +1028,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
>    asection *newsect;
>    flagword flags;
>    const struct elf_backend_data *bed;
> +  unsigned int opb = bfd_octets_per_byte (abfd, NULL);
>
>    if (hdr->bfd_section != NULL)
>      return TRUE;
> @@ -1046,11 +1047,6 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
>
>    newsect->filepos = hdr->sh_offset;
>
> -  if (!bfd_set_section_vma (newsect, hdr->sh_addr)
> -      || !bfd_set_section_size (newsect, hdr->sh_size)
> -      || !bfd_set_section_alignment (newsect, bfd_log2
> (hdr->sh_addralign))) -    return FALSE;
> -
>    flags = SEC_NO_FLAGS;
>    if (hdr->sh_type != SHT_NOBITS)
>      flags |= SEC_HAS_CONTENTS;
> @@ -1108,7 +1104,10 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
>  	    flags |= SEC_DEBUGGING | SEC_ELF_OCTETS;
>  	  else if (strncmp (name, GNU_BUILD_ATTRS_SECTION_NAME, 21) == 0
>
>  		   || strncmp (name, ".note.gnu", 9) == 0)
>
> -	    flags |= SEC_ELF_OCTETS;
> +	    {
> +	      flags |= SEC_ELF_OCTETS;
> +	      opb = 1;
> +	    }
>  	  else if (strncmp (name, ".line", 5) == 0
>
>  		   || strncmp (name, ".stab", 5) == 0
>  		   || strcmp (name, ".gdb_index") == 0)
>
> @@ -1116,6 +1115,11 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
>  	}
>      }
>
> +  if (!bfd_set_section_vma (newsect, hdr->sh_addr / opb)
> +      || !bfd_set_section_size (newsect, hdr->sh_size)
> +      || !bfd_set_section_alignment (newsect, bfd_log2
> (hdr->sh_addralign))) +    return FALSE;
> +
>    /* 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.
> @@ -1177,7 +1181,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
>  	    {
>  	      if ((flags & SEC_LOAD) == 0)
>  		newsect->lma = (phdr->p_paddr
> -				+ hdr->sh_addr - phdr->p_vaddr);
> +				+ hdr->sh_addr - phdr->p_vaddr) / opb;
>  	      else
>  		/* We used to use the same adjustment for SEC_LOAD
>  		   sections, but that doesn't work if the segment
> @@ -1187,7 +1191,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
>  		   segment will contain sections with contiguous
>  		   LMAs, even if the VMAs are not.  */
>  		newsect->lma = (phdr->p_paddr
> -				+ hdr->sh_offset - phdr->p_offset);
> +				+ hdr->sh_offset - phdr->p_offset) / opb;
>
>  	      /* With contiguous segments, we can't tell from file
>  		 offsets whether a section with zero size should
> @@ -2970,6 +2974,7 @@ _bfd_elf_make_section_from_phdr (bfd *abfd,
>    char namebuf[64];
>    size_t len;
>    int split;
> +  unsigned int opb = bfd_octets_per_byte (abfd, NULL);
>
>    split = ((hdr->p_memsz > 0)
>  	    && (hdr->p_filesz > 0)
> @@ -2986,8 +2991,8 @@ _bfd_elf_make_section_from_phdr (bfd *abfd,
>        newsect = bfd_make_section (abfd, name);
>        if (newsect == NULL)
>  	return FALSE;
> -      newsect->vma = hdr->p_vaddr;
> -      newsect->lma = hdr->p_paddr;
> +      newsect->vma = hdr->p_vaddr / opb;
> +      newsect->lma = hdr->p_paddr / opb;
>        newsect->size = hdr->p_filesz;
>        newsect->filepos = hdr->p_offset;
>        newsect->flags |= SEC_HAS_CONTENTS;
> @@ -3022,8 +3027,8 @@ _bfd_elf_make_section_from_phdr (bfd *abfd,
>        newsect = bfd_make_section (abfd, name);
>        if (newsect == NULL)
>  	return FALSE;
> -      newsect->vma = hdr->p_vaddr + hdr->p_filesz;
> -      newsect->lma = hdr->p_paddr + hdr->p_filesz;
> +      newsect->vma = (hdr->p_vaddr + hdr->p_filesz) / opb;
> +      newsect->lma = (hdr->p_paddr + hdr->p_filesz) / opb;
>        newsect->size = hdr->p_memsz - hdr->p_filesz;
>        newsect->filepos = hdr->p_offset + hdr->p_filesz;
>        align = newsect->vma & -newsect->vma;
> @@ -3299,7 +3304,7 @@ elf_fake_sections (bfd *abfd, asection *asect, void
> *fsarg)
>
>    if ((asect->flags & SEC_ALLOC) != 0
>
>        || asect->user_set_vma)
>
> -    this_hdr->sh_addr = asect->vma;
> +    this_hdr->sh_addr = asect->vma * bfd_octets_per_byte (abfd, asect);
>    else
>      this_hdr->sh_addr = 0;
>
> @@ -4685,6 +4690,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct
> bfd_link_info *info) bfd_size_type amt;
>        bfd_vma addr_mask, wrap_to = 0;
>        bfd_size_type phdr_size;
> +      unsigned int opb = bfd_octets_per_byte (abfd, NULL);
>
>        /* Select the allocated sections, and sort them.  */
>
> @@ -4724,6 +4730,8 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct
> bfd_link_info *info) if (phdr_size == (bfd_size_type) -1)
>  	phdr_size = get_program_header_size (abfd, info);
>        phdr_size += bed->s->sizeof_ehdr;
> +      /* phdr_size is compared to LMA values which are in bytes */
> +      phdr_size /= opb;
>        maxpagesize = bed->maxpagesize;
>        if (maxpagesize == 0)
>  	maxpagesize = 1;
> @@ -4948,7 +4956,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct
> bfd_link_info *info) executable = TRUE;
>  	      last_hdr = hdr;
>  	      /* .tbss sections effectively have zero size.  */
> -	      last_size = !IS_TBSS (hdr) ? hdr->size : 0;
> +	      last_size = (!IS_TBSS (hdr) ? hdr->size : 0) / opb;
>  	      continue;
>  	    }
>
> @@ -4974,7 +4982,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct
> bfd_link_info *info)
>
>  	  last_hdr = hdr;
>  	  /* .tbss sections effectively have zero size.  */
> -	  last_size = !IS_TBSS (hdr) ? hdr->size : 0;
> +	  last_size = (!IS_TBSS (hdr) ? hdr->size : 0) / opb;
>  	  hdr_index = i;
>  	  phdr_in_segment = FALSE;
>  	}
> @@ -5428,11 +5436,12 @@ assign_file_positions_for_load_sections (bfd *abfd,
>    struct elf_segment_map *phdr_load_seg;
>    Elf_Internal_Phdr *phdrs;
>    Elf_Internal_Phdr *p;
> -  file_ptr off;
> +  file_ptr off;  /* octets */
>    bfd_size_type maxpagesize;
>    unsigned int alloc, actual;
>    unsigned int i, j;
>    struct elf_segment_map **sorted_seg_map;
> +  unsigned int opb = bfd_octets_per_byte (abfd, NULL);
>
>    if (link_info == NULL
>        && !_bfd_elf_map_sections_to_segments (abfd, link_info))
> @@ -5540,7 +5549,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
>    for (j = 0; j < alloc; j++)
>      {
>        asection **secpp;
> -      bfd_vma off_adjust;
> +      bfd_vma off_adjust;  /* octets */
>        bfd_boolean no_contents;
>
>        /* An ELF segment (described by Elf_Internal_Phdr) may contain a
> @@ -5554,16 +5563,16 @@ assign_file_positions_for_load_sections (bfd *abfd,
>        p->p_flags = m->p_flags;
>
>        if (m->count == 0)
> -	p->p_vaddr = m->p_vaddr_offset;
> +	p->p_vaddr = m->p_vaddr_offset * opb;
>        else
> -	p->p_vaddr = m->sections[0]->vma + m->p_vaddr_offset;
> +	p->p_vaddr = (m->sections[0]->vma + m->p_vaddr_offset) * opb;
>
>        if (m->p_paddr_valid)
>  	p->p_paddr = m->p_paddr;
>        else if (m->count == 0)
>  	p->p_paddr = 0;
>        else
> -	p->p_paddr = m->sections[0]->lma + m->p_vaddr_offset;
> +	p->p_paddr = (m->sections[0]->lma + m->p_vaddr_offset) * opb;
>
>        if (p->p_type == PT_LOAD
>  	  && (abfd->flags & D_PAGED) != 0)
> @@ -5644,7 +5653,8 @@ assign_file_positions_for_load_sections (bfd *abfd,
>  	      && (abfd->flags & D_PAGED) != 0
>  	      && bed->no_page_alias
>  	      && (off & (maxpagesize - 1)) != 0
> -	      && (off & -maxpagesize) == ((off + off_adjust) & -maxpagesize))
> +	      && ((off & -maxpagesize)
> +		  == ((off + off_adjust) & -maxpagesize)))
>  	    off_adjust += maxpagesize;
>  	  off += off_adjust;
>  	  if (no_contents)
> @@ -5735,7 +5745,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
>  	      else if (phdr_load_seg != NULL)
>  		{
>  		  Elf_Internal_Phdr *phdr = phdrs + phdr_load_seg->idx;
> -		  bfd_vma phdr_off = 0;
> +		  bfd_vma phdr_off = 0;  /* octets */
>  		  if (phdr_load_seg->includes_filehdr)
>  		    phdr_off = bed->s->sizeof_ehdr;
>  		  p->p_vaddr = phdr->p_vaddr + phdr_off;
> @@ -5755,7 +5765,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
>  	    p->p_offset = off;
>  	  else
>  	    {
> -	      file_ptr adjust;
> +	      file_ptr adjust;  /* octets */
>
>  	      adjust = off - (p->p_offset + p->p_filesz);
>  	      if (!no_contents)
> @@ -5786,10 +5796,10 @@ assign_file_positions_for_load_sections (bfd *abfd,
>  		      && ((this_hdr->sh_flags & SHF_TLS) == 0
>
>  			  || p->p_type == PT_TLS))))
>
>  	    {
> -	      bfd_vma p_start = p->p_paddr;
> -	      bfd_vma p_end = p_start + p->p_memsz;
> -	      bfd_vma s_start = sec->lma;
> -	      bfd_vma adjust = s_start - p_end;
> +	      bfd_vma p_start = p->p_paddr;                /* octets */
> +	      bfd_vma p_end = p_start + p->p_memsz;        /* octets */
> +	      bfd_vma s_start = sec->lma * opb;            /* octets */
> +	      bfd_vma adjust = s_start - p_end;            /* octets */
>
>  	      if (adjust != 0
>  		  && (s_start < p_end
> @@ -5798,9 +5808,10 @@ assign_file_positions_for_load_sections (bfd *abfd,
>  		  _bfd_error_handler
>  		    /* xgettext:c-format */
>  		    (_("%pB: section %pA lma %#" PRIx64 " adjusted to %#" PRIx64),
> -		     abfd, sec, (uint64_t) s_start, (uint64_t) p_end);
> +		     abfd, sec, (uint64_t) s_start / opb,
> +		     (uint64_t) p_end / opb);
>  		  adjust = 0;
> -		  sec->lma = p_end;
> +		  sec->lma = p_end / opb;
>  		}
>  	      p->p_memsz += adjust;
>
> @@ -6186,8 +6197,11 @@ assign_file_positions_for_non_load_sections (bfd
> *abfd,
>
>  		  if (i < lm->count)
>  		    {
> -		      p->p_vaddr = lm->sections[i]->vma;
> -		      p->p_paddr = lm->sections[i]->lma;
> +		      unsigned int opb = bfd_octets_per_byte (abfd,
> +							      lm->sections[i]);
> +
> +		      p->p_vaddr = lm->sections[i]->vma * opb;
> +		      p->p_paddr = lm->sections[i]->lma * opb;
>  		      p->p_offset = lm->sections[i]->filepos;
>  		      p->p_memsz = end - p->p_vaddr;
>  		      p->p_filesz = p->p_memsz;
> @@ -6786,6 +6800,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
>    struct elf_segment_map *phdr_adjust_seg = NULL;
>    unsigned int phdr_adjust_num = 0;
>    const struct elf_backend_data *bed;
> +  unsigned int opb = bfd_octets_per_byte (ibfd, NULL);
>
>    bed = get_elf_backend_data (ibfd);
>    iehdr = elf_elfheader (ibfd);
> @@ -6808,17 +6823,17 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
>
>    /* Returns TRUE if the given section is contained within
>       the given segment.  VMA addresses are compared.  */
> -#define IS_CONTAINED_BY_VMA(section, segment)				\
> -  (section->vma >= segment->p_vaddr					\
> -   && (section->vma + SECTION_SIZE (section, segment)			\
> +#define IS_CONTAINED_BY_VMA(section, segment, opb)			\
> +  (section->vma * (opb) >= segment->p_vaddr				\
> +   && (section->vma * (opb) + SECTION_SIZE (section, segment)		\
>         <= (SEGMENT_END (segment, segment->p_vaddr))))
>
>    /* Returns TRUE if the given section is contained within
>       the given segment.  LMA addresses are compared.  */
> -#define IS_CONTAINED_BY_LMA(section, segment, base)			\
> -  (section->lma >= base							\
> -   && (section->lma + SECTION_SIZE (section, segment) >= section->lma)	\
> -   && (section->lma + SECTION_SIZE (section, segment)			\
> +#define IS_CONTAINED_BY_LMA(section, segment, base, opb)		\
> +  (section->lma * (opb) >= base						\
> +   && (section->lma * (opb) + SECTION_SIZE (section, segment) >=
> section->lma) \ +   && (section->lma * (opb) + SECTION_SIZE (section,
> segment)		\
>         <= SEGMENT_END (segment, base)))
>
>    /* Handle PT_NOTE segment.  */
> @@ -6864,10 +6879,10 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
>         7. SHF_TLS sections are only in PT_TLS or PT_LOAD segments.
>         8. PT_DYNAMIC should not contain empty sections at the beginning
>  	  (with the possible exception of .dynamic).  */
> -#define IS_SECTION_IN_INPUT_SEGMENT(section, segment, bed)		\
> +#define IS_SECTION_IN_INPUT_SEGMENT(section, segment, bed, opb)		\
>    ((((segment->p_paddr							\
> -      ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr)	\
> -      : IS_CONTAINED_BY_VMA (section, segment))				\
> +      ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr, opb)	\
> +      : IS_CONTAINED_BY_VMA (section, segment, opb))			\
>       && (section->flags & SEC_ALLOC) != 0)				\
>
>      || IS_NOTE (segment, section))					\
>
>     && segment->p_type != PT_GNU_STACK					\
> @@ -6879,15 +6894,15 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
>     && (segment->p_type != PT_DYNAMIC					\
>
>         || SECTION_SIZE (section, segment) > 0				\
>         || (segment->p_paddr						\
>
> -	   ? segment->p_paddr != section->lma				\
> -	   : segment->p_vaddr != section->vma)				\
> +	   ? segment->p_paddr != section->lma * (opb)			\
> +	   : segment->p_vaddr != section->vma * (opb))			\
>
>         || (strcmp (bfd_section_name (section), ".dynamic") == 0))	\
>
>     && (segment->p_type != PT_LOAD || !section->segment_mark))
>
>  /* If the output section of a section in the input segment is NULL,
>     it is removed from the corresponding output segment.   */
> -#define INCLUDE_SECTION_IN_SEGMENT(section, segment, bed)		\
> -  (IS_SECTION_IN_INPUT_SEGMENT (section, segment, bed)		\
> +#define INCLUDE_SECTION_IN_SEGMENT(section, segment, bed, opb)		\
> +  (IS_SECTION_IN_INPUT_SEGMENT (section, segment, bed, opb)		\
>     && section->output_section != NULL)
>
>    /* Returns TRUE iff seg1 starts after the end of seg2.  */
> @@ -6941,7 +6956,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
>  	    {
>  	      /* Mininal change so that the normal section to segment
>  		 assignment code will work.  */
> -	      segment->p_vaddr = section->vma;
> +	      segment->p_vaddr = section->vma * opb;
>  	      break;
>  	    }
>
> @@ -7027,7 +7042,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
>  	{
>  	  /* Find the first section in the input segment, which may be
>  	     removed from the corresponding output segment.   */
> -	  if (IS_SECTION_IN_INPUT_SEGMENT (section, segment, bed))
> +	  if (IS_SECTION_IN_INPUT_SEGMENT (section, segment, bed, opb))
>  	    {
>  	      if (first_section == NULL)
>  		first_section = section;
> @@ -7095,7 +7110,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
>  		 " at vaddr=%#" PRIx64 ", is this intentional?"),
>  	       ibfd, (uint64_t) segment->p_vaddr);
>
> -	  map->p_vaddr_offset = segment->p_vaddr;
> +	  map->p_vaddr_offset = segment->p_vaddr / opb;
>  	  map->count = 0;
>  	  *pointer_to_map = map;
>  	  pointer_to_map = &map->next;
> @@ -7149,7 +7164,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
>  	   section != NULL;
>  	   section = section->next)
>  	{
> -	  if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed))
> +	  if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed, opb))
>  	    {
>  	      output_section = section->output_section;
>
> @@ -7176,10 +7191,11 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
>
>  	      /* Match up the physical address of the segment with the
>  		 LMA address of the output section.  */
> -	      if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr)
> +	      if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr,
> +				       opb)
>
>  		  || IS_COREFILE_NOTE (segment, section)
>  		  || (bed->want_p_paddr_set_to_zero
>
> -		      && IS_CONTAINED_BY_VMA (output_section, segment)))
> +		      && IS_CONTAINED_BY_VMA (output_section, segment, opb)))
>  		{
>  		  if (matching_lma == NULL
>
>  		      || output_section->lma < matching_lma->lma)
>
> @@ -7223,7 +7239,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
>
>  	      /* Account for padding before the first section in the
>  		 segment.  */
> -	      map->p_vaddr_offset = map->p_paddr + hdr_size - matching_lma->lma;
> +	      map->p_vaddr_offset = ((map->p_paddr + hdr_size) / opb
> +				     - matching_lma->lma);
>  	    }
>
>  	  free (sections);
> @@ -7294,7 +7311,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
>
>  	      BFD_ASSERT (output_section != NULL);
>
> -	      if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr)
> +	      if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr,
> +				       opb)
>
>  		  || IS_COREFILE_NOTE (segment, section))
>
>  		{
>  		  if (map->count == 0)
> @@ -7445,6 +7463,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
>    unsigned int num_segments;
>    bfd_boolean phdr_included = FALSE;
>    bfd_boolean p_paddr_valid;
> +  unsigned int opb = bfd_octets_per_byte (ibfd, NULL);
>
>    iehdr = elf_elfheader (ibfd);
>
> @@ -7570,7 +7589,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
>  			seg_off = this_hdr->sh_offset - segment->p_offset;
>  		      else
>  			seg_off = this_hdr->sh_addr - segment->p_vaddr;
> -		      if (section->lma - segment->p_paddr != seg_off)
> +		      if (section->lma * opb - segment->p_paddr != seg_off)
>  			map->p_paddr_valid = FALSE;
>  		    }
>  		  if (isec == section_count)
> @@ -7580,7 +7599,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
>  	}
>
>        if (section_count == 0)
> -	map->p_vaddr_offset = segment->p_vaddr;
> +	map->p_vaddr_offset = segment->p_vaddr / opb;
>        else if (map->p_paddr_valid)
>  	{
>  	  /* Account for padding before the first section in the segment.  */
> @@ -7590,7 +7609,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
>  	  if (map->includes_phdrs)
>  	    hdr_size += iehdr->e_phnum * iehdr->e_phentsize;
>
> -	  map->p_vaddr_offset = (map->p_paddr + hdr_size
> +	  map->p_vaddr_offset = ((map->p_paddr + hdr_size) / opb
>  				 - (lowest_section ? lowest_section->lma : 0));
>  	}
>
> diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c
> index a1a5ce11be1..1524a05cc50 100644
> --- a/bfd/elf32-rx.c
> +++ b/bfd/elf32-rx.c
> @@ -26,6 +26,9 @@
>  #include "libiberty.h"
>  #include "elf32-rx.h"
>
> +/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1.  */
> +#define OCTETS_PER_BYTE(ABFD, SEC) 1
> +
>  #define RX_OPCODE_BIG_ENDIAN 0
>
>  /* This is a meta-target that's used only with objcopy, to avoid the
> @@ -3306,7 +3309,10 @@ rx_elf_object_p (bfd * abfd)
>  	      && phdr[i].p_vaddr <= bsec->vma
>  	      && bsec->vma <= phdr[i].p_vaddr + (phdr[i].p_filesz - 1))
>  	    {
> -	      bsec->lma = phdr[i].p_paddr + (bsec->vma - phdr[i].p_vaddr);
> +	      bsec->lma = (phdr[i].p_paddr / OCTETS_PER_BYTE (abfd, bsec)
> +			   + (bsec->vma
> +			      - (phdr[i].p_vaddr
> +				 / OCTETS_PER_BYTE (abfd, bsec))));
>  	    }
>  	  bsec = bsec->next;
>  	}
> diff --git a/bfd/elf64-ia64-vms.c b/bfd/elf64-ia64-vms.c
> index d0cb7e08e10..6a3bd793a3d 100644
> --- a/bfd/elf64-ia64-vms.c
> +++ b/bfd/elf64-ia64-vms.c
> @@ -30,6 +30,9 @@
>  #include "vms.h"
>  #include "bfdver.h"
>
> +/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1.  */
> +#define OCTETS_PER_BYTE(ABFD, SEC) 1
> +
>  /* THE RULES for all the stuff the linker creates --
>
>    GOT		Entries created in response to LTOFF or LTOFF_FPTR
> @@ -4833,8 +4836,8 @@ elf64_vms_link_add_object_symbols (bfd *abfd, struct
> bfd_link_info *info) s = bfd_make_section (abfd, ".dynamic");
>  		if (s == NULL)
>  		  goto error_return;
> -		s->vma = phdr->p_vaddr;
> -		s->lma = phdr->p_paddr;
> +		s->vma = phdr->p_vaddr / OCTETS_PER_BYTE (abfd, s);
> +		s->lma = phdr->p_paddr / OCTETS_PER_BYTE (abfd, s);
>  		s->size = phdr->p_filesz;
>  		s->filepos = phdr->p_offset;
>  		s->flags |= SEC_HAS_CONTENTS;
> diff --git a/bfd/elflink.c b/bfd/elflink.c
> index 7078a2fb6f4..e09ab908b60 100644
> --- a/bfd/elflink.c
> +++ b/bfd/elflink.c
> @@ -4227,11 +4227,15 @@ error_free_dyn:
>  	if (phdr->p_type == PT_GNU_RELRO)
>  	  {
>  	    for (s = abfd->sections; s != NULL; s = s->next)
> -	      if ((s->flags & SEC_ALLOC) != 0
> -		  && s->vma >= phdr->p_vaddr
> -		  && s->vma + s->size <= phdr->p_vaddr + phdr->p_memsz)
> -		s->flags |= SEC_READONLY;
> -	    break;
> +	      {
> +		unsigned int opb = bfd_octets_per_byte (abfd, s);
> +
> +		if ((s->flags & SEC_ALLOC) != 0
> +		    && s->vma * opb >= phdr->p_vaddr
> +		    && s->vma * opb + s->size <= phdr->p_vaddr + phdr->p_memsz)
> +		  s->flags |= SEC_READONLY;
> +		break;
> +	      }
>  	  }
>
>        /* We do not want to include any of the sections in a dynamic
> diff --git a/include/elf/internal.h b/include/elf/internal.h
> index 794c16812ee..4ede98aa54d 100644
> --- a/include/elf/internal.h
> +++ b/include/elf/internal.h
> @@ -86,11 +86,11 @@ typedef struct elf_internal_ehdr {
>  struct elf_internal_phdr {
>    unsigned long	p_type;			/* Identifies program segment type */
>    unsigned long	p_flags;		/* Segment flags */
> -  bfd_vma	p_offset;		/* Segment file offset */
> -  bfd_vma	p_vaddr;		/* Segment virtual address */
> -  bfd_vma	p_paddr;		/* Segment physical address */
> -  bfd_vma	p_filesz;		/* Segment size in file */
> -  bfd_vma	p_memsz;		/* Segment size in memory */
> +  bfd_vma	p_offset;		/* Segment file offset in octets */
> +  bfd_vma	p_vaddr;		/* Segment virtual address in octets */
> +  bfd_vma	p_paddr;		/* Segment physical address in octets */
> +  bfd_vma	p_filesz;		/* Segment size in file in octets */
> +  bfd_vma	p_memsz;		/* Segment size in memory in octets */
>    bfd_vma	p_align;		/* Segment alignment, file & memory */
>  };
>
> @@ -102,9 +102,10 @@ typedef struct elf_internal_shdr {
>    unsigned int	sh_name;		/* Section name, index in string tbl */
>    unsigned int	sh_type;		/* Type of section */
>    bfd_vma	sh_flags;		/* Miscellaneous section attributes */
> -  bfd_vma	sh_addr;		/* Section virtual addr at execution */
> -  file_ptr	sh_offset;		/* Section file offset */
> -  bfd_size_type	sh_size;		/* Size of section in bytes */
> +  bfd_vma	sh_addr;		/* Section virtual addr at execution in
> +					   octets */
> +  file_ptr	sh_offset;		/* Section file offset in octets */
> +  bfd_size_type	sh_size;		/* Size of section in octets */
>    unsigned int	sh_link;		/* Index of another section */
>    unsigned int	sh_info;		/* Additional section information */
>    bfd_vma	sh_addralign;		/* Section alignment */
> @@ -267,7 +268,7 @@ struct elf_segment_map
>    unsigned long p_flags;
>    /* Program segment physical address.  */
>    bfd_vma p_paddr;
> -  /* Program segment virtual address offset from section vma.  */
> +  /* Program segment virtual address offset from section vma in bytes.  */
>    bfd_vma p_vaddr_offset;
>    /* Program segment alignment.  */
>    bfd_vma p_align;
> diff --git a/ld/ldexp.c b/ld/ldexp.c
> index b287022f5a1..9c599c2d470 100644
> --- a/ld/ldexp.c
> +++ b/ld/ldexp.c
> @@ -700,7 +700,8 @@ fold_name (etree_type *tree)
>  	  /* Don't find the real header size if only marking sections;
>  	     The bfd function may cache incorrect data.  */
>  	  if (expld.phase != lang_mark_phase_enum)
> -	    hdr_size = bfd_sizeof_headers (link_info.output_bfd, &link_info);
> +	    hdr_size = (bfd_sizeof_headers (link_info.output_bfd, &link_info)
> +			/ bfd_octets_per_byte (link_info.output_bfd, NULL));
>  	  new_number (hdr_size);
>  	}
>        break;
> --
> 2.16.4






More information about the Binutils mailing list