[2/2] Fix several mix up between octets and bytes in ELF program headers

Message ID 20200215193050.22717-3-ceggers@gmx.de
State Superseded
Headers show
Series
  • [1/2] Fix several mix up between octets and bytes in ELF program headers
Related show

Commit Message

Christian Eggers Feb. 15, 2020, 7:30 p.m.
This is a follow-up patch for my patch from december 09 with the same
subject. It fixes additional locations not handled in the first patch.

When converting between addresses in ELF headers [octets] and bfd
LMA/VMA [bytes], the number of octets per byte needs to be incorperated.

include/
	* bfdlink.h (struct bfd_link_order): Add unit (bytes/octets) to
	offset and size members.
	* elf/internal.h (struct elf_internal_phdr): likewise for
	p_align member.
	(struct elf_segment_map): likewise for p_paddr and p_size
	members

bfd/
	* bfd.c (bfd_record_phdr): New local "opb". Fix assignment of
	"p_paddr" from "at".
	* elfcode.h (bfd_from_remote_memory): Add units to several
	parameters. New local "opb". Fix usage of p_align. Fix
	calculation of "localbase" from "ehdr_vma" and "p_vaddr". Fix
	call of target_read_memory().
	* elflink.c (elf_fixup_link_order): Fix scope of "s" local. Fix
	calculation of "offset" and "output_offset".
	(bfd_elf_final_link): New local "opb". Fix calculation of "size"
	from "offset" and fix calculation of "end" from "vma+size". Fix
	comparison between "sh_addr" and "vma"/"output_offset".
	(bfd_elf_discard_info): Fix calculation of "eh_alignment".
	* elf-bfd.h (struct elf_link_hash_table): Add unit to tls_size
	member.
	* elf.c (_bfd_elf_map_sections_to_segments): Add unit (bytes/
	octets) to "wrap_to2 and "phdr_size" locals. Fix calculation of
	"wrap_to" value. Add unit (bytes) to phdr_lma variable. Fix
	assignment of p_paddr from phdr_lma. Fix comparison between "lma
	+size" and "next->lma".
	(elf_sort_segments): Fix assignment from p_paddr to lma.
	(assign_file_positions_for_load_sections): Add unit (bytes) to
	local "align". Fix calculation of local "off_adjust". Fix
	calculation of local "filehdr_vaddr".
	(assign_file_positions_for_non_load_sections): New local "opb".
	Fix calculation of "end" from "p_size". Fix comparison between
	"vma+SECTION_SIZE()" and "start". Fix calculation of "p_memsz"
	from "end" and "p_vaddr".
	(rewrite_elf_program_header): Fix comparison between p_vaddr and
	vma. Fix assignment to p_paddr from lma. Fix comparison between
	p_paddr and lma. Fix assignment to p_paddr from lma.
	* merge.c (sec_merge_emit): New local "opb". Convert
	"alignment_power" to octets.
	(_bfd_add_merge_section): New locals "alignment_power" and
	"opb". Fix comparison between "alignment_power" and
	"sizeof(align)".
	(_bfd_merge_sections): New local "opb". Divide size by opb
	before checking align mask.

Signed-off-by: Christian Eggers <ceggers@gmx.de>

---
 bfd/bfd.c              |  5 +++--
 bfd/elf-bfd.h          |  2 +-
 bfd/elf.c              | 54 +++++++++++++++++++++++++-------------------------
 bfd/elfcode.h          | 28 ++++++++++++++------------
 bfd/elflink.c          | 31 +++++++++++++++++------------
 bfd/merge.c            | 22 ++++++++++++--------
 include/bfdlink.h      |  4 ++--
 include/elf/internal.h |  7 ++++---
 8 files changed, 84 insertions(+), 69 deletions(-)

--
2.16.4

Comments

Nick Clifton March 2, 2020, 2:18 p.m. | #1
Hi Christian,

> include/

> 	* bfdlink.h (struct bfd_link_order): Add unit (bytes/octets) to

> 	offset and size members.

> 	* elf/internal.h (struct elf_internal_phdr): likewise for

> 	p_align member.

> 	(struct elf_segment_map): likewise for p_paddr and p_size

> 	members

> 

> bfd/

> 	* bfd.c (bfd_record_phdr): New local "opb". Fix assignment of

> 	"p_paddr" from "at".

> 	* elfcode.h (bfd_from_remote_memory): Add units to several

> 	parameters. New local "opb". Fix usage of p_align. Fix

> 	calculation of "localbase" from "ehdr_vma" and "p_vaddr". Fix

> 	call of target_read_memory().

> 	* elflink.c (elf_fixup_link_order): Fix scope of "s" local. Fix

> 	calculation of "offset" and "output_offset".

> 	(bfd_elf_final_link): New local "opb". Fix calculation of "size"

> 	from "offset" and fix calculation of "end" from "vma+size". Fix

> 	comparison between "sh_addr" and "vma"/"output_offset".

> 	(bfd_elf_discard_info): Fix calculation of "eh_alignment".

> 	* elf-bfd.h (struct elf_link_hash_table): Add unit to tls_size

> 	member.

> 	* elf.c (_bfd_elf_map_sections_to_segments): Add unit (bytes/

> 	octets) to "wrap_to2 and "phdr_size" locals. Fix calculation of

> 	"wrap_to" value. Add unit (bytes) to phdr_lma variable. Fix

> 	assignment of p_paddr from phdr_lma. Fix comparison between "lma

> 	+size" and "next->lma".

> 	(elf_sort_segments): Fix assignment from p_paddr to lma.

> 	(assign_file_positions_for_load_sections): Add unit (bytes) to

> 	local "align". Fix calculation of local "off_adjust". Fix

> 	calculation of local "filehdr_vaddr".

> 	(assign_file_positions_for_non_load_sections): New local "opb".

> 	Fix calculation of "end" from "p_size". Fix comparison between

> 	"vma+SECTION_SIZE()" and "start". Fix calculation of "p_memsz"

> 	from "end" and "p_vaddr".

> 	(rewrite_elf_program_header): Fix comparison between p_vaddr and

> 	vma. Fix assignment to p_paddr from lma. Fix comparison between

> 	p_paddr and lma. Fix assignment to p_paddr from lma.

> 	* merge.c (sec_merge_emit): New local "opb". Convert

> 	"alignment_power" to octets.

> 	(_bfd_add_merge_section): New locals "alignment_power" and

> 	"opb". Fix comparison between "alignment_power" and

> 	"sizeof(align)".

> 	(_bfd_merge_sections): New local "opb". Divide size by opb

> 	before checking align mask.


Approved - please apply - but please fixup the comments first.

Cheers
  Nick

Patch

diff --git a/bfd/bfd.c b/bfd/bfd.c
index b1050626b68..5802985099a 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -2162,7 +2162,7 @@  bfd_record_phdr (bfd *abfd,
 		 bfd_boolean flags_valid,
 		 flagword flags,
 		 bfd_boolean at_valid,
-		 bfd_vma at,
+		 bfd_vma at,  /* bytes */
 		 bfd_boolean includes_filehdr,
 		 bfd_boolean includes_phdrs,
 		 unsigned int count,
@@ -2170,6 +2170,7 @@  bfd_record_phdr (bfd *abfd,
 {
   struct elf_segment_map *m, **pm;
   bfd_size_type amt;
+  unsigned int opb = bfd_octets_per_byte (abfd, NULL);

   if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
     return TRUE;
@@ -2182,7 +2183,7 @@  bfd_record_phdr (bfd *abfd,

   m->p_type = type;
   m->p_flags = flags;
-  m->p_paddr = at;
+  m->p_paddr = at * opb;
   m->p_flags_valid = flags_valid;
   m->p_paddr_valid = at_valid;
   m->includes_filehdr = includes_filehdr;
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index cbbba153f49..f74afacc976 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -635,7 +635,7 @@  struct elf_link_hash_table

   /* Cached first output tls section and size of PT_TLS segment.  */
   asection *tls_sec;
-  bfd_size_type tls_size;
+  bfd_size_type tls_size;  /* bytes */

   /* A linked list of BFD's loaded in the link.  */
   struct elf_link_loaded_list *loaded;
diff --git a/bfd/elf.c b/bfd/elf.c
index d941b33b15c..fbc45f6d30f 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -4688,8 +4688,8 @@  _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
       asection *first_mbind = NULL;
       asection *dynsec, *eh_frame_hdr;
       bfd_size_type amt;
-      bfd_vma addr_mask, wrap_to = 0;
-      bfd_size_type phdr_size;
+      bfd_vma addr_mask, wrap_to = 0;  /* bytes */
+      bfd_size_type phdr_size;  /* octets/bytes */
       unsigned int opb = bfd_octets_per_byte (abfd, NULL);

       /* Select the allocated sections, and sort them.  */
@@ -4717,8 +4717,8 @@  _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
 	      sections[i] = s;
 	      ++i;
 	      /* A wrapping section potentially clashes with header.  */
-	      if (((s->lma + s->size) & addr_mask) < (s->lma & addr_mask))
-		wrap_to = (s->lma + s->size) & addr_mask;
+	      if (((s->lma + s->size / opb) & addr_mask) < (s->lma & addr_mask))
+		wrap_to = (s->lma + s->size / opb) & addr_mask;
 	    }
 	}
       BFD_ASSERT (i <= bfd_count_sections (abfd));
@@ -4802,7 +4802,7 @@  _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
 	 program headers we will need.  */
       if (phdr_in_segment && count > 0)
 	{
-	  bfd_vma phdr_lma;
+	  bfd_vma phdr_lma;  /* bytes */
 	  bfd_boolean separate_phdr = FALSE;

 	  phdr_lma = (sections[0]->lma - phdr_size) & addr_mask & -maxpagesize;
@@ -4842,7 +4842,7 @@  _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
 	      m = make_mapping (abfd, sections, 0, 0, phdr_in_segment);
 	      if (m == NULL)
 		goto error_return;
-	      m->p_paddr = phdr_lma;
+	      m->p_paddr = phdr_lma * opb;
 	      m->p_vaddr_offset
 		= (sections[0]->vma - phdr_size) & addr_mask & -maxpagesize;
 	      m->p_paddr_valid = 1;
@@ -5030,7 +5030,7 @@  _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
 		  if (s2->next->alignment_power == alignment_power
 		      && (s2->next->flags & SEC_LOAD) != 0
 		      && elf_section_type (s2->next) == SHT_NOTE
-		      && align_power (s2->lma + s2->size,
+		      && align_power (s2->lma + s2->size / opb,
 				      alignment_power)
 		      == s2->next->lma)
 		    count++;
@@ -5328,15 +5328,17 @@  elf_sort_segments (const void *arg1, const void *arg2)
     return m1->no_sort_lma ? -1 : 1;
   if (m1->p_type == PT_LOAD && !m1->no_sort_lma)
     {
-      bfd_vma lma1, lma2;
+      unsigned int opb = bfd_octets_per_byte (m1->sections[0]->owner,
+					      m1->sections[0]);
+      bfd_vma lma1, lma2;  /* bytes */
       lma1 = 0;
       if (m1->p_paddr_valid)
-	lma1 = m1->p_paddr;
+	lma1 = m1->p_paddr / opb;
       else if (m1->count != 0)
 	lma1 = m1->sections[0]->lma + m1->p_vaddr_offset;
       lma2 = 0;
       if (m2->p_paddr_valid)
-	lma2 = m2->p_paddr;
+	lma2 = m2->p_paddr / opb;
       else if (m2->count != 0)
 	lma2 = m2->sections[0]->lma + m2->p_vaddr_offset;
       if (lma1 != lma2)
@@ -5607,7 +5609,7 @@  assign_file_positions_for_load_sections (bfd *abfd,
       if (p->p_type == PT_LOAD
 	  && m->count > 0)
 	{
-	  bfd_size_type align;
+	  bfd_size_type align;  /* bytes */
 	  unsigned int align_power = 0;

 	  if (m->p_align_valid)
@@ -5644,7 +5646,7 @@  assign_file_positions_for_load_sections (bfd *abfd,
 		break;
 	      }

-	  off_adjust = vma_page_aligned_bias (p->p_vaddr, off, align);
+	  off_adjust = vma_page_aligned_bias (p->p_vaddr, off, align * opb);

 	  /* Broken hardware and/or kernel require that files do not
 	     map the same page with different permissions on some hppa
@@ -6007,7 +6009,7 @@  assign_file_positions_for_load_sections (bfd *abfd,
 	      || hash->root.type == bfd_link_hash_common))
 	{
 	  asection *s = NULL;
-	  bfd_vma filehdr_vaddr = phdrs[phdr_load_seg->idx].p_vaddr;
+	  bfd_vma filehdr_vaddr = phdrs[phdr_load_seg->idx].p_vaddr / opb;

 	  if (phdr_load_seg->count != 0)
 	    /* The segment contains sections, so use the first one.  */
@@ -6084,6 +6086,7 @@  assign_file_positions_for_non_load_sections (bfd *abfd,
   Elf_Internal_Phdr *p;
   struct elf_segment_map *m;
   file_ptr off;
+  unsigned int opb = bfd_octets_per_byte (abfd, NULL);

   i_shdrpp = elf_elfsections (abfd);
   end_hdrpp = i_shdrpp + elf_numsections (abfd);
@@ -6150,7 +6153,7 @@  assign_file_positions_for_non_load_sections (bfd *abfd,
     {
       if (p->p_type == PT_GNU_RELRO)
 	{
-	  bfd_vma start, end;
+	  bfd_vma start, end;  /* bytes */
 	  bfd_boolean ok;

 	  if (link_info != NULL)
@@ -6166,7 +6169,7 @@  assign_file_positions_for_non_load_sections (bfd *abfd,
 	      if (!m->p_size_valid)
 		abort ();
 	      start = m->sections[0]->vma;
-	      end = start + m->p_size;
+	      end = start + m->p_size / opb;
 	    }
 	  else
 	    {
@@ -6191,7 +6194,7 @@  assign_file_positions_for_non_load_sections (bfd *abfd,
 		      && lm->count != 0
 		      && (lm->sections[lm->count - 1]->vma
 			  + (!IS_TBSS (lm->sections[lm->count - 1])
-			     ? lm->sections[lm->count - 1]->size
+			     ? lm->sections[lm->count - 1]->size / opb
 			     : 0)) > start
 		      && lm->sections[0]->vma < end)
 		    break;
@@ -6211,13 +6214,10 @@  assign_file_positions_for_non_load_sections (bfd *abfd,

 		  if (i < lm->count)
 		    {
-		      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_memsz = end * opb - p->p_vaddr;
 		      p->p_filesz = p->p_memsz;

 		      /* The RELRO segment typically ends a few bytes
@@ -7199,8 +7199,8 @@  rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
 				   + (map->includes_phdrs
 				      ? iehdr->e_phnum * iehdr->e_phentsize
 				      : 0),
-				   output_section->alignment_power)
-		      == output_section->vma))
+				   output_section->alignment_power * opb)
+		      == (output_section->vma * opb)))
 		map->p_paddr = segment->p_vaddr;

 	      /* Match up the physical address of the segment with the
@@ -7268,7 +7268,7 @@  rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
 	  if (matching_lma == NULL)
 	    matching_lma = suggested_lma;

-	  map->p_paddr = matching_lma->lma;
+	  map->p_paddr = matching_lma->lma * opb;

 	  /* Offset the segment physical address from the lma
 	     to allow for space taken up by elf headers.  */
@@ -7296,7 +7296,7 @@  rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
 		 the same alignment.  */
 	      if (segment->p_align != 0 && segment->p_align < align)
 		align = segment->p_align;
-	      map->p_paddr &= -align;
+	      map->p_paddr &= -(align * opb);
 	    }
 	}

@@ -7340,8 +7340,8 @@  rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
 				       + (map->includes_phdrs
 					  ? iehdr->e_phnum * iehdr->e_phentsize
 					  : 0),
-				       output_section->alignment_power)
-			  != output_section->lma)
+				       output_section->alignment_power * opb)
+			  != output_section->lma * opb)
 			goto sorry;
 		    }
 		  else
@@ -7407,7 +7407,7 @@  rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
 	      map->p_type = segment->p_type;
 	      map->p_flags = segment->p_flags;
 	      map->p_flags_valid = 1;
-	      map->p_paddr = suggested_lma->lma;
+	      map->p_paddr = suggested_lma->lma * opb;
 	      map->p_paddr_valid = p_paddr_valid;
 	      map->includes_filehdr = 0;
 	      map->includes_phdrs = 0;
diff --git a/bfd/elfcode.h b/bfd/elfcode.h
index e1e89cf78f2..9ffdba56b66 100644
--- a/bfd/elfcode.h
+++ b/bfd/elfcode.h
@@ -1635,10 +1635,11 @@  elf_debug_file (Elf_Internal_Ehdr *ehdrp)
 bfd *
 NAME(_bfd_elf,bfd_from_remote_memory)
   (bfd *templ,
-   bfd_vma ehdr_vma,
-   bfd_size_type size,
-   bfd_vma *loadbasep,
+   bfd_vma ehdr_vma    /* bytes */,
+   bfd_size_type size  /* octets */,
+   bfd_vma *loadbasep  /* bytes */,
    int (*target_read_memory) (bfd_vma, bfd_byte *, bfd_size_type))
+                          /* (bytes  ,           , octets       )*/
 {
   Elf_External_Ehdr x_ehdr;	/* Elf file header, external form */
   Elf_Internal_Ehdr i_ehdr;	/* Elf file header, internal form */
@@ -1651,8 +1652,9 @@  NAME(_bfd_elf,bfd_from_remote_memory)
   unsigned int i;
   bfd_vma high_offset;
   bfd_vma shdr_end;
-  bfd_vma loadbase;
+  bfd_vma loadbase;  /* bytes */
   char *filename;
+  unsigned int opb = bfd_octets_per_byte (templ, NULL);

   /* Read in the ELF header in external format.  */
   err = target_read_memory (ehdr_vma, (bfd_byte *) &x_ehdr, sizeof x_ehdr);
@@ -1746,17 +1748,17 @@  NAME(_bfd_elf,bfd_from_remote_memory)
 	     header sits, then we can figure out the loadbase.  */
 	  if (first_phdr == NULL)
 	    {
-	      bfd_vma p_offset = i_phdrs[i].p_offset;
-	      bfd_vma p_vaddr = i_phdrs[i].p_vaddr;
+	      bfd_vma p_offset = i_phdrs[i].p_offset;  /* octets */
+	      bfd_vma p_vaddr = i_phdrs[i].p_vaddr;    /* octets */

 	      if (i_phdrs[i].p_align > 1)
 		{
-		  p_offset &= -i_phdrs[i].p_align;
-		  p_vaddr &= -i_phdrs[i].p_align;
+		  p_offset &= -(i_phdrs[i].p_align * opb);
+		  p_vaddr &= -(i_phdrs[i].p_align * opb);
 		}
 	      if (p_offset == 0)
 		{
-		  loadbase = ehdr_vma - p_vaddr;
+		  loadbase = ehdr_vma - p_vaddr / opb;
 		  first_phdr = &i_phdrs[i];
 		}
 	    }
@@ -1812,9 +1814,9 @@  NAME(_bfd_elf,bfd_from_remote_memory)
   for (i = 0; i < i_ehdr.e_phnum; ++i)
     if (i_phdrs[i].p_type == PT_LOAD)
       {
-	bfd_vma start = i_phdrs[i].p_offset;
-	bfd_vma end = start + i_phdrs[i].p_filesz;
-	bfd_vma vaddr = i_phdrs[i].p_vaddr;
+	bfd_vma start = i_phdrs[i].p_offset;         /* octets */
+	bfd_vma end = start + i_phdrs[i].p_filesz;   /* octets */
+	bfd_vma vaddr = i_phdrs[i].p_vaddr;          /* octets */

 	/* Extend the beginning of the first pt_load to cover file
 	   header and program headers, if we proved earlier that its
@@ -1827,7 +1829,7 @@  NAME(_bfd_elf,bfd_from_remote_memory)
 	/* Extend the end of the last pt_load to cover section headers.  */
 	if (last_phdr == &i_phdrs[i])
 	  end = high_offset;
-	err = target_read_memory (loadbase + vaddr,
+	err = target_read_memory (loadbase + vaddr / opb,
 				  contents + start, end - start);
 	if (err)
 	  {
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 43fbbf0dd1b..788fd803f35 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -11570,8 +11570,8 @@  elf_fixup_link_order (bfd *abfd, asection *o)
   struct bfd_link_order *p;
   bfd *sub;
   struct bfd_link_order **sections;
-  asection *s, *other_sec, *linkorder_sec;
-  bfd_vma offset;
+  asection *other_sec, *linkorder_sec;
+  bfd_vma offset;  /* octets */

   other_sec = NULL;
   linkorder_sec = NULL;
@@ -11581,7 +11581,7 @@  elf_fixup_link_order (bfd *abfd, asection *o)
     {
       if (p->type == bfd_indirect_link_order)
 	{
-	  s = p->u.indirect.section;
+	  asection *s = p->u.indirect.section;
 	  sub = s->owner;
 	  if ((s->flags & SEC_LINKER_CREATED) == 0
 	      && bfd_get_flavour (sub) == bfd_target_elf_flavour
@@ -11636,11 +11636,12 @@  elf_fixup_link_order (bfd *abfd, asection *o)
   for (n = 0; n < seen_linkorder; n++)
     {
       bfd_vma mask;
-      s = sections[n]->u.indirect.section;
-      mask = ~(bfd_vma) 0 << s->alignment_power;
+      asection *s = sections[n]->u.indirect.section;
+      unsigned int opb = bfd_octets_per_byte (abfd, s);
+
+      mask = ~(bfd_vma) 0 << s->alignment_power * opb;
       offset = (offset + ~mask) & mask;
-      s->output_offset = offset / bfd_octets_per_byte (abfd, s);
-      sections[n]->offset = offset;
+      sections[n]->offset = s->output_offset = offset / opb;
       offset += sections[n]->size;
     }

@@ -12250,7 +12251,7 @@  bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)

   if (htab->tls_sec)
     {
-      bfd_vma base, end = 0;
+      bfd_vma base, end = 0;  /* both bytes */
       asection *sec;

       for (sec = htab->tls_sec;
@@ -12258,6 +12259,7 @@  bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 	   sec = sec->next)
 	{
 	  bfd_size_type size = sec->size;
+	  unsigned int opb = bfd_octets_per_byte (abfd, sec);

 	  if (size == 0
 	      && (sec->flags & SEC_HAS_CONTENTS) == 0)
@@ -12265,9 +12267,9 @@  bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 	      struct bfd_link_order *ord = sec->map_tail.link_order;

 	      if (ord != NULL)
-		size = ord->offset + ord->size;
+		size = ord->offset * opb + ord->size;
 	    }
-	  end = sec->vma + size;
+	  end = sec->vma + size / opb;
 	}
       base = htab->tls_sec->vma;
       /* Only align end of TLS section if static TLS doesn't have special
@@ -12780,6 +12782,8 @@  bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)

 	      if (bed->dtrel_excludes_plt && htab->srelplt != NULL)
 		{
+		  unsigned int opb = bfd_octets_per_byte (abfd, o);
+
 		  /* Don't count procedure linkage table relocs in the
 		     overall reloc count.  */
 		  sh_size -= htab->srelplt->size;
@@ -12799,7 +12803,7 @@  bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 		  /* If .rela.plt is the first .rela section, exclude
 		     it from DT_RELA.  */
 		  else if (sh_addr == (htab->srelplt->output_section->vma
-				       + htab->srelplt->output_offset))
+				       + htab->srelplt->output_offset) * opb)
 		    sh_addr += htab->srelplt->size;
 		}

@@ -14254,7 +14258,7 @@  bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
     {
       asection *i;
       int eh_changed = 0;
-      unsigned int eh_alignment;
+      unsigned int eh_alignment;  /* octets */

       for (i = o->map_head.s; i != NULL; i = i->map_head.s)
 	{
@@ -14281,7 +14285,8 @@  bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
 	  fini_reloc_cookie_for_section (&cookie, i);
 	}

-      eh_alignment = 1 << o->alignment_power;
+      eh_alignment = ((1 << o->alignment_power)
+		      * bfd_octets_per_byte (output_bfd, o));
       /* Skip over zero terminator, and prevent empty sections from
 	 adding alignment padding at the end.  */
       for (i = o->map_tail.s; i != NULL; i = i->map_tail.s)
diff --git a/bfd/merge.c b/bfd/merge.c
index 2ed1ef595c4..59805325273 100644
--- a/bfd/merge.c
+++ b/bfd/merge.c
@@ -292,8 +292,9 @@  sec_merge_emit (bfd *abfd, struct sec_merge_hash_entry *entry,
   asection *sec = secinfo->sec;
   char *pad = NULL;
   bfd_size_type off = 0;
-  int alignment_power = sec->output_section->alignment_power;
-  bfd_size_type pad_len;
+  unsigned int opb = bfd_octets_per_byte (abfd, sec);
+  int alignment_power = sec->output_section->alignment_power * opb;
+  bfd_size_type pad_len;  /* octets */

   /* FIXME: If alignment_power is 0 then really we should scan the
      entry list for the largest required alignment and use that.  */
@@ -364,9 +365,11 @@  _bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec,
 {
   struct sec_merge_info *sinfo;
   struct sec_merge_sec_info *secinfo;
-  unsigned int align;
+  unsigned int alignment_power;  /* octets */
+  unsigned int align;            /* octets */
   bfd_size_type amt;
   bfd_byte *contents;
+  unsigned int opb = bfd_octets_per_byte (abfd, sec);

   if ((abfd->flags & DYNAMIC) != 0
       || (sec->flags & SEC_MERGE) == 0)
@@ -389,10 +392,11 @@  _bfd_add_merge_section (bfd *abfd, void **psinfo, asection *sec,
 #ifndef CHAR_BIT
 #define CHAR_BIT 8
 #endif
-  if (sec->alignment_power >= sizeof (align) * CHAR_BIT)
+  alignment_power = sec->alignment_power * opb;
+  if (alignment_power >= sizeof (align) * CHAR_BIT)
     return TRUE;

-  align = 1u << sec->alignment_power;
+  align = 1u << alignment_power;
   if ((sec->entsize < align
        && ((sec->entsize & (sec->entsize - 1))
 	   || !(sec->flags & SEC_STRINGS)))
@@ -739,7 +743,7 @@  _bfd_merge_sections (bfd *abfd,
   for (sinfo = (struct sec_merge_info *) xsinfo; sinfo; sinfo = sinfo->next)
     {
       struct sec_merge_sec_info *secinfo;
-      bfd_size_type align;
+      bfd_size_type align;  /* bytes */

       if (! sinfo->chain)
 	continue;
@@ -764,8 +768,10 @@  _bfd_merge_sections (bfd *abfd,
 	      return FALSE;
 	    if (align)
 	      {
+		unsigned int opb = bfd_octets_per_byte (abfd, secinfo->sec);
+
 		align = (bfd_size_type) 1 << secinfo->sec->alignment_power;
-		if ((secinfo->sec->size & (align - 1)) != 0)
+		if (((secinfo->sec->size / opb) & (align - 1)) != 0)
 		  align = 0;
 	      }
 	  }
@@ -782,7 +788,7 @@  _bfd_merge_sections (bfd *abfd,
       else
 	{
 	  struct sec_merge_hash_entry *e;
-	  bfd_size_type size = 0;
+	  bfd_size_type size = 0;  /* octets */

 	  /* Things are much simpler for non-strings.
 	     Just assign them slots in the section.  */
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 8d85530e390..40a6d4d40a6 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -801,9 +801,9 @@  struct bfd_link_order
   struct bfd_link_order *next;
   /* Type of link_order.  */
   enum bfd_link_order_type type;
-  /* Offset within output section.  */
+  /* Offset within output section in bytes.  */
   bfd_vma offset;
-  /* Size within output section.  */
+  /* Size within output section in octets.  */
   bfd_size_type size;
   /* Type specific information.  */
   union
diff --git a/include/elf/internal.h b/include/elf/internal.h
index c436e64fe56..c9be57fa1f7 100644
--- a/include/elf/internal.h
+++ b/include/elf/internal.h
@@ -91,7 +91,8 @@  struct elf_internal_phdr {
   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 */
+  bfd_vma	p_align;		/* Segment alignment in bytes, file
+					   & memory */
 };

 typedef struct elf_internal_phdr Elf_Internal_Phdr;
@@ -266,13 +267,13 @@  struct elf_segment_map
   unsigned long p_type;
   /* Program segment flags.  */
   unsigned long p_flags;
-  /* Program segment physical address.  */
+  /* Program segment physical address in octets.  */
   bfd_vma p_paddr;
   /* Program segment virtual address offset from section vma in bytes.  */
   bfd_vma p_vaddr_offset;
   /* Program segment alignment.  */
   bfd_vma p_align;
-  /* Segment size in file and memory */
+  /* Segment size in file and memory in octets.  */
   bfd_vma p_size;
   /* Whether the p_flags field is valid; if not, the flags are based
      on the section flags.  */