[6/9,bfd] Introduce new section flag: SEC_ELF_OCTETS

Message ID 20191121211732.16653-7-ceggers@gmx.de
State New
Headers show
Series
  • ELF support for targets with octets_per_byte>1
Related show

Commit Message

Christian Eggers Nov. 21, 2019, 9:17 p.m.
All symbols, sizes and relocations in this section are octets instead of
bytes. Required for DWARF debug sections as DWARF information is
organized in octets, not bytes.

	* section.c (struct bfd_section): New flag SEC_ELF_OCTETS.
	* archures.c (bfd_octets_per_byte): New parameter sec.
	If section is not NULL and SEC_ELF_OCTETS is set, one octet es
	returned [ELF targets only].
	* bfd.c (bfd_get_section_limit): Provide section parameter to
	bfd_octets_per_byte().
	* bfd-in2.h: regenerate.
	* binary.c (binary_set_section_contents): Move call to
	bfd_octets_per_byte() into section loop. Provide section parameter
	to bfd_octets_per_byte().
	* coff-arm.c (coff_arm_reloc): Provide section parameter
	to bfd_octets_per_byte().
	* coff-i386.c (coff_i386_reloc): likewise.
	* coff-mips.c (mips_reflo_reloc): likewise.
	* coff-x86_64.c (coff_amd64_reloc): likewise.
	* cofflink.c (_bfd_coff_link_input_bfd): likewise.
	(_bfd_coff_reloc_link_order): likewise.
	* elf.c (_bfd_elf_section_offset): likewise.
	(_bfd_elf_make_section_from_shdr): likewise.
	Set SEC_ELF_OCTETS for sections with names .gnu.build.attributes,
	.debug*, .zdebug* and .note.gnu*.
	* elf32-msp430.c (rl78_sym_diff_handler): Provide section parameter
	to bfd_octets_per_byte().
	* elf32-nds.c (nds32_elf_get_relocated_section_contents): likewise.
	* elf32-ppc.c (ppc_elf_addr16_ha_reloc): likewise.
	* elf32-pru.c (pru_elf32_do_ldi32_relocate): likewise.
	* elf32-s12z.c (opru18_reloc): likewise.
	* elf32-sh.c (sh_elf_reloc): likewise.
	* elf32-spu.c (spu_elf_rel9): likewise.
	* elf32-xtensa.c (bfd_elf_xtensa_reloc): likewise
	* elf64-ppc.c (ppc64_elf_brtaken_reloc): likewise.
	(ppc64_elf_addr16_ha_reloc): likewise.
	(ppc64_elf_toc64_reloc): likewise.
	* elflink.c (bfd_elf_final_link): likewise.
	(bfd_elf_perform_complex_relocation): likewise.
	(elf_fixup_link_order): likewise.
	(elf_link_input_bfd): likewise.
	(elf_link_sort_relocs): likewise.
	(elf_reloc_link_order): likewise.
	(resolve_section): likewise.
	* linker.c (_bfd_generic_reloc_link_order): likewise.
	(bfd_generic_define_common_symbol): likewise.
	(default_data_link_order): likewise.
	(default_indirect_link_order): likewise.
	* srec.c (srec_set_section_contents): likewise.
	(srec_write_section): likewise.
	* syms.c (_bfd_stab_section_find_nearest_line): likewise.
	* reloc.c (_bfd_final_link_relocate): likewise.
	(bfd_generic_get_relocated_section_contents): likewise.
	(bfd_install_relocation): likewise.
	For section which have SEC_ELF_OCTETS set, multiply output_base
	and output_offset with bfd_octets_per_byte().
	(bfd_perform_relocation): likewise.

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

---
 bfd/archures.c     | 15 +++++++++++----
 bfd/bfd-in2.h      | 11 +++++++++--
 bfd/bfd.c          |  3 ++-
 bfd/binary.c       |  4 ++--
 bfd/coff-arm.c     |  2 +-
 bfd/coff-i386.c    |  2 +-
 bfd/coff-mips.c    |  2 +-
 bfd/coff-x86_64.c  |  2 +-
 bfd/cofflink.c     |  5 +++--
 bfd/elf.c          | 12 +++++++++++-
 bfd/elf32-msp430.c |  2 +-
 bfd/elf32-nds32.c  |  2 +-
 bfd/elf32-ppc.c    |  2 +-
 bfd/elf32-pru.c    |  4 ++--
 bfd/elf32-s12z.c   |  3 ++-
 bfd/elf32-sh.c     |  3 ++-
 bfd/elf32-spu.c    |  2 +-
 bfd/elf32-xtensa.c |  3 ++-
 bfd/elf64-ppc.c    |  6 +++---
 bfd/elflink.c      | 19 +++++++++++--------
 bfd/linker.c       |  9 +++++----
 bfd/reloc.c        | 32 +++++++++++++++++++++++++-------
 bfd/section.c      |  5 +++++
 bfd/srec.c         |  5 +++--
 bfd/syms.c         |  8 +++++---
 25 files changed, 111 insertions(+), 52 deletions(-)

--
2.16.4

Patch

diff --git a/bfd/archures.c b/bfd/archures.c
index 569876eed0..5fb9ca0fe6 100644
--- a/bfd/archures.c
+++ b/bfd/archures.c
@@ -1379,7 +1379,8 @@  FUNCTION
 	bfd_octets_per_byte

 SYNOPSIS
-	unsigned int bfd_octets_per_byte (const bfd *abfd);
+	unsigned int bfd_octets_per_byte (const bfd *abfd,
+					  const asection *sec);

 DESCRIPTION
 	Return the number of octets (8-bit quantities) per target byte
@@ -1388,10 +1389,16 @@  DESCRIPTION
 */

 unsigned int
-bfd_octets_per_byte (const bfd *abfd)
+bfd_octets_per_byte (const bfd *abfd, const asection *sec)
 {
-  return bfd_arch_mach_octets_per_byte (bfd_get_arch (abfd),
-					bfd_get_mach (abfd));
+  unsigned int opb = bfd_arch_mach_octets_per_byte (bfd_get_arch (abfd),
+						    bfd_get_mach (abfd));
+
+  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour &&
+      sec && (sec->flags & SEC_ELF_OCTETS))
+    opb = 1;
+
+  return opb;
 }

 /*
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 3244905b45..0e8e1b81c6 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -992,6 +992,11 @@  typedef struct bfd_section
   /* This section contains vliw code.  This is for Toshiba MeP only.  */
 #define SEC_MEP_VLIW               0x20000000

+  /* All symbols, sizes and relocations in this section are octets
+     instead of bytes. Required for DWARF debug sections as DWARF
+     information is organized in octets, not bytes. */
+#define SEC_ELF_OCTETS             0x40000000
+
   /* Indicate that section has the no read flag set. This happens
      when memory read flag isn't set. */
 #define SEC_COFF_NOREAD            0x40000000
@@ -1993,7 +1998,8 @@  const bfd_arch_info_type *bfd_lookup_arch
 const char *bfd_printable_arch_mach
    (enum bfd_architecture arch, unsigned long machine);

-unsigned int bfd_octets_per_byte (const bfd *abfd);
+unsigned int bfd_octets_per_byte (const bfd *abfd,
+    const asection *sec);

 unsigned int bfd_arch_mach_octets_per_byte
    (enum bfd_architecture arch, unsigned long machine);
@@ -6854,7 +6860,8 @@  bfd_get_section_limit_octets (const bfd *abfd, const asection *sec)
 static inline bfd_size_type
 bfd_get_section_limit (const bfd *abfd, const asection *sec)
 {
-  return bfd_get_section_limit_octets (abfd, sec) / bfd_octets_per_byte (abfd);
+  return (bfd_get_section_limit_octets (abfd, sec)
+          / bfd_octets_per_byte (abfd, NULL));
 }

 /* Functions to handle insertion and deletion of a bfd's sections.  These
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 94e9f27e9d..4db8b35e3a 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -492,7 +492,8 @@  CODE_FRAGMENT
 .static inline bfd_size_type
 .bfd_get_section_limit (const bfd *abfd, const asection *sec)
 .{
-.  return bfd_get_section_limit_octets (abfd, sec) / bfd_octets_per_byte (abfd);
+.  return (bfd_get_section_limit_octets (abfd, sec)
+.	   / bfd_octets_per_byte (abfd, NULL));
 .}
 .
 .{* Functions to handle insertion and deletion of a bfd's sections.  These
diff --git a/bfd/binary.c b/bfd/binary.c
index eb87d11b6e..06dfdf7b6e 100644
--- a/bfd/binary.c
+++ b/bfd/binary.c
@@ -230,7 +230,6 @@  binary_set_section_contents (bfd *abfd,

   if (! abfd->output_has_begun)
     {
-      unsigned int opb;
       bfd_boolean found_low;
       bfd_vma low;
       asection *s;
@@ -251,9 +250,10 @@  binary_set_section_contents (bfd *abfd,
 	    found_low = TRUE;
 	  }

-      opb = bfd_octets_per_byte (abfd);
       for (s = abfd->sections; s != NULL; s = s->next)
 	{
+	  unsigned int opb = bfd_octets_per_byte (abfd, s);
+
 	  s->filepos = (s->lma - low) * opb;

 	  /* Skip following warning check for sections that will not
diff --git a/bfd/coff-arm.c b/bfd/coff-arm.c
index c9a7c098f5..e297df27e8 100644
--- a/bfd/coff-arm.c
+++ b/bfd/coff-arm.c
@@ -118,7 +118,7 @@  coff_arm_reloc (bfd *abfd,

       if (! bfd_reloc_offset_in_range (howto, abfd, input_section,
 				       reloc_entry->address
-				       * bfd_octets_per_byte (abfd)))
+				       * bfd_octets_per_byte (abfd, NULL)))
 	return bfd_reloc_outofrange;

       switch (howto->size)
diff --git a/bfd/coff-i386.c b/bfd/coff-i386.c
index 9810fd71be..f28eb8af0c 100644
--- a/bfd/coff-i386.c
+++ b/bfd/coff-i386.c
@@ -146,7 +146,7 @@  coff_i386_reloc (bfd *abfd,

       if (! bfd_reloc_offset_in_range (howto, abfd, input_section,
 				       reloc_entry->address
-				       * bfd_octets_per_byte (abfd)))
+				       * bfd_octets_per_byte (abfd, NULL)))
 	return bfd_reloc_outofrange;

       switch (howto->size)
diff --git a/bfd/coff-mips.c b/bfd/coff-mips.c
index c6fe679a6c..c9c7fc66ba 100644
--- a/bfd/coff-mips.c
+++ b/bfd/coff-mips.c
@@ -507,7 +507,7 @@  mips_reflo_reloc (bfd *abfd ATTRIBUTE_UNUSED,
 	  if (! bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
 					   input_section,
 					   reloc_entry->address
-					   * bfd_octets_per_byte (abfd)))
+					   * bfd_octets_per_byte (abfd, NULL)))
 	    return bfd_reloc_outofrange;

 	  /* Do the REFHI relocation.  Note that we actually don't
diff --git a/bfd/coff-x86_64.c b/bfd/coff-x86_64.c
index c5e9a346ae..94fd7ac3e4 100644
--- a/bfd/coff-x86_64.c
+++ b/bfd/coff-x86_64.c
@@ -145,7 +145,7 @@  coff_amd64_reloc (bfd *abfd,

       if (! bfd_reloc_offset_in_range (howto, abfd, input_section,
 				       reloc_entry->address
-				       * bfd_octets_per_byte (abfd)))
+				       * bfd_octets_per_byte (abfd, NULL)))
 	return bfd_reloc_outofrange;

       switch (howto->size)
diff --git a/bfd/cofflink.c b/bfd/cofflink.c
index 2115e9c36a..23a8e6b226 100644
--- a/bfd/cofflink.c
+++ b/bfd/cofflink.c
@@ -2541,7 +2541,8 @@  _bfd_coff_link_input_bfd (struct coff_final_link_info *flaginfo, bfd *input_bfd)
       /* Write out the modified section contents.  */
       if (secdata == NULL || secdata->stab_info == NULL)
 	{
-	  file_ptr loc = o->output_offset * bfd_octets_per_byte (output_bfd);
+	  file_ptr loc = (o->output_offset
+			  * bfd_octets_per_byte (output_bfd, NULL));
 	  if (! bfd_set_section_contents (output_bfd, o->output_section,
 					  contents, loc, o->size))
 	    return FALSE;
@@ -2852,7 +2853,7 @@  _bfd_coff_reloc_link_order (bfd *output_bfd,
 	     (bfd *) NULL, (asection *) NULL, (bfd_vma) 0);
 	  break;
 	}
-      loc = link_order->offset * bfd_octets_per_byte (output_bfd);
+      loc = link_order->offset * bfd_octets_per_byte (output_bfd, NULL);
       ok = bfd_set_section_contents (output_bfd, output_section, buf,
 				     loc, size);
       free (buf);
diff --git a/bfd/elf.c b/bfd/elf.c
index be060d579c..e0c3d967c4 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1121,6 +1121,15 @@  _bfd_elf_make_section_from_shdr (bfd *abfd,
 	    p = NULL, n = 0;
 	  if (p != NULL && strncmp (name, p, n) == 0)
 	    flags |= SEC_DEBUGGING;
+
+	  /* DWARF debug sections and ELF notes are organized in octets. */
+	  if (strncmp (name, ".debug", 6) == 0 ||
+	      strncmp (name, ".zdebug", 7) == 0 ||
+	      strncmp (name, GNU_BUILD_ATTRS_SECTION_NAME, 21) == 0 ||
+	      strncmp (name, ".note.gnu", 9) == 0)
+	    {
+	      flags |= SEC_ELF_OCTETS;
+	    }
 	}
     }

@@ -12060,7 +12069,8 @@  _bfd_elf_section_offset (bfd *abfd,

 	  /* address_size and sec->size are in octets.  Convert
 	     to bytes before subtracting the original offset.  */
-	  offset = (sec->size - address_size) / bfd_octets_per_byte (abfd) - offset;
+	  offset = ((sec->size - address_size)
+		    / bfd_octets_per_byte (abfd, NULL) - offset);
 	}
       return offset;
     }
diff --git a/bfd/elf32-msp430.c b/bfd/elf32-msp430.c
index d581dbcd93..7f675fcc34 100644
--- a/bfd/elf32-msp430.c
+++ b/bfd/elf32-msp430.c
@@ -36,7 +36,7 @@  rl78_sym_diff_handler (bfd * abfd,
 		       char ** error_message ATTRIBUTE_UNUSED)
 {
   bfd_size_type octets;
-  octets = reloc->address * bfd_octets_per_byte (abfd);
+  octets = reloc->address * bfd_octets_per_byte (abfd, NULL);

   /* Catch the case where bfd_install_relocation would return
      bfd_reloc_outofrange because the SYM_DIFF reloc is being used in a very
diff --git a/bfd/elf32-nds32.c b/bfd/elf32-nds32.c
index 482fb290d1..a47d98e270 100644
--- a/bfd/elf32-nds32.c
+++ b/bfd/elf32-nds32.c
@@ -13220,7 +13220,7 @@  nds32_elf_get_relocated_section_contents (bfd *abfd,
 		= HOWTO (0, 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL,
 			 "unused", FALSE, 0, 0, FALSE);

-	      off = (*parent)->address * bfd_octets_per_byte (input_bfd);
+	      off = (*parent)->address * bfd_octets_per_byte (input_bfd, NULL);
 	      _bfd_clear_contents ((*parent)->howto, input_bfd,
 				   input_section, data, off);
 	      (*parent)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index cb6cd114af..187f747978 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -956,7 +956,7 @@  ppc_elf_addr16_ha_reloc (bfd *abfd,
 	    + input_section->output_section->vma);
   value >>= 16;

-  octets = reloc_entry->address * bfd_octets_per_byte (abfd);
+  octets = reloc_entry->address * bfd_octets_per_byte (abfd, NULL);
   insn = bfd_get_32 (abfd, (bfd_byte *) data + octets);
   insn &= ~0x1fffc1;
   insn |= (value & 0xffc1) | ((value & 0x3e) << 15);
diff --git a/bfd/elf32-pru.c b/bfd/elf32-pru.c
index 054f1650f2..98b2018621 100644
--- a/bfd/elf32-pru.c
+++ b/bfd/elf32-pru.c
@@ -537,7 +537,7 @@  pru_elf32_do_ldi32_relocate (bfd *abfd, reloc_howto_type *howto,
 			     bfd_vma symbol_value, bfd_vma addend)
 {
   bfd_signed_vma relocation;
-  bfd_size_type octets = offset * bfd_octets_per_byte (abfd);
+  bfd_size_type octets = offset * bfd_octets_per_byte (abfd, NULL);
   bfd_byte *location;
   unsigned long in1, in2;

@@ -557,7 +557,7 @@  pru_elf32_do_ldi32_relocate (bfd *abfd, reloc_howto_type *howto,
   BFD_ASSERT (!howto->pc_relative);

   /* A hacked-up version of _bfd_relocate_contents() follows.  */
-  location = data + offset * bfd_octets_per_byte (abfd);
+  location = data + offset * bfd_octets_per_byte (abfd, NULL);

   BFD_ASSERT (!howto->pc_relative);

diff --git a/bfd/elf32-s12z.c b/bfd/elf32-s12z.c
index ba6498505a..8b3099c26e 100644
--- a/bfd/elf32-s12z.c
+++ b/bfd/elf32-s12z.c
@@ -43,7 +43,8 @@  opru18_reloc (bfd *abfd, arelent *reloc_entry, struct bfd_symbol *symbol,
      is shifted one place to the left of where it would normally be.  See
      Appendix A.4 of the S12Z reference manual.  */

-  bfd_size_type octets = reloc_entry->address * bfd_octets_per_byte (abfd);
+  bfd_size_type octets = (reloc_entry->address
+			  * bfd_octets_per_byte (abfd, NULL));
   bfd_vma result = bfd_get_24 (abfd, (unsigned char *) data + octets);
   bfd_vma val = bfd_asymbol_value (symbol);

diff --git a/bfd/elf32-sh.c b/bfd/elf32-sh.c
index c572f709f2..17390260df 100644
--- a/bfd/elf32-sh.c
+++ b/bfd/elf32-sh.c
@@ -254,7 +254,8 @@  sh_elf_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol_in,
     return bfd_reloc_undefined;

   /* PR 17512: file: 9891ca98.  */
-  if (addr * bfd_octets_per_byte (abfd) + bfd_get_reloc_size (reloc_entry->howto)
+  if ((addr * bfd_octets_per_byte (abfd, NULL)
+       + bfd_get_reloc_size (reloc_entry->howto))
       > bfd_get_section_limit_octets (abfd, input_section))
     return bfd_reloc_outofrange;

diff --git a/bfd/elf32-spu.c b/bfd/elf32-spu.c
index b557c865b3..89d9f9b8ce 100644
--- a/bfd/elf32-spu.c
+++ b/bfd/elf32-spu.c
@@ -212,7 +212,7 @@  spu_elf_rel9 (bfd *abfd, arelent *reloc_entry, asymbol *symbol,

   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
     return bfd_reloc_outofrange;
-  octets = reloc_entry->address * bfd_octets_per_byte (abfd);
+  octets = reloc_entry->address * bfd_octets_per_byte (abfd, NULL);

   /* Get symbol value.  */
   val = 0;
diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
index 306b18b4f2..31e9530256 100644
--- a/bfd/elf32-xtensa.c
+++ b/bfd/elf32-xtensa.c
@@ -2103,7 +2103,8 @@  bfd_elf_xtensa_reloc (bfd *abfd,
 {
   bfd_vma relocation;
   bfd_reloc_status_type flag;
-  bfd_size_type octets = reloc_entry->address * bfd_octets_per_byte (abfd);
+  bfd_size_type octets = (reloc_entry->address
+			  * bfd_octets_per_byte (abfd, NULL));
   bfd_vma output_base = 0;
   reloc_howto_type *howto = reloc_entry->howto;
   asection *reloc_target_output_section;
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 4ece6fbde0..5c7f32315f 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -1405,7 +1405,7 @@  ppc64_elf_ha_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
 	    + input_section->output_section->vma);
   value = (bfd_signed_vma) value >> 16;

-  octets = reloc_entry->address * bfd_octets_per_byte (abfd);
+  octets = reloc_entry->address * bfd_octets_per_byte (abfd, NULL);
   insn = bfd_get_32 (abfd, (bfd_byte *) data + octets);
   insn &= ~0x1fffc1;
   insn |= (value & 0xffc1) | ((value & 0x3e) << 15);
@@ -1480,7 +1480,7 @@  ppc64_elf_brtaken_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
     return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
 				  input_section, output_bfd, error_message);

-  octets = reloc_entry->address * bfd_octets_per_byte (abfd);
+  octets = reloc_entry->address * bfd_octets_per_byte (abfd, NULL);
   insn = bfd_get_32 (abfd, (bfd_byte *) data + octets);
   insn &= ~(0x01 << 21);
   r_type = reloc_entry->howto->type;
@@ -1630,7 +1630,7 @@  ppc64_elf_toc64_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
   if (TOCstart == 0)
     TOCstart = ppc64_elf_set_toc (NULL, input_section->output_section->owner);

-  octets = reloc_entry->address * bfd_octets_per_byte (abfd);
+  octets = reloc_entry->address * bfd_octets_per_byte (abfd, NULL);
   bfd_put_64 (abfd, TOCstart + TOC_BASE_OFF, (bfd_byte *) data + octets);
   return bfd_reloc_ok;
 }
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 9d7f69afda..824669a536 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -8456,7 +8456,8 @@  resolve_section (const char *name,
 	{
 	  if (strncmp (".end", name + len, 4) == 0)
 	    {
-	      *result = curr->vma + curr->size / bfd_octets_per_byte (abfd);
+	      *result = (curr->vma
+			 + curr->size / bfd_octets_per_byte (abfd, NULL));
 	      return TRUE;
 	    }

@@ -8778,7 +8779,8 @@  bfd_elf_perform_complex_relocation (bfd *input_bfd,
     shift = (8 * wordsz) - (start + len);

   x = get_value (wordsz, chunksz, input_bfd,
-		 contents + rel->r_offset * bfd_octets_per_byte (input_bfd));
+		 contents
+		 + rel->r_offset * bfd_octets_per_byte (input_bfd, NULL));

 #ifdef DEBUG
   printf ("Doing complex reloc: "
@@ -8811,7 +8813,7 @@  bfd_elf_perform_complex_relocation (bfd *input_bfd,
 	  (unsigned long) ((relocation & mask) << shift), (unsigned long) x);
 #endif
   put_value (wordsz, chunksz, input_bfd, x,
-	     contents + rel->r_offset * bfd_octets_per_byte (input_bfd));
+	     contents + rel->r_offset * bfd_octets_per_byte (input_bfd, NULL));
   return r;
 }

@@ -9175,7 +9177,7 @@  elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec)
   struct elf_link_sort_rela *sq;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   int i2e = bed->s->int_rels_per_ext_rel;
-  unsigned int opb = bfd_octets_per_byte (abfd);
+  unsigned int opb = bfd_octets_per_byte (abfd, NULL);
   void (*swap_in) (bfd *, const bfd_byte *, Elf_Internal_Rela *);
   void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
   struct bfd_link_order *lo;
@@ -11303,7 +11305,7 @@  elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
 		file_ptr offset = (file_ptr) o->output_offset;
 		bfd_size_type todo = o->size;

-		offset *= bfd_octets_per_byte (output_bfd);
+		offset *= bfd_octets_per_byte (output_bfd, NULL);

 		if ((o->flags & SEC_ELF_REVERSE_COPY))
 		  {
@@ -11465,7 +11467,7 @@  elf_reloc_link_order (bfd *output_bfd,

       ok = bfd_set_section_contents (output_bfd, output_section, buf,
 				     link_order->offset
-				     * bfd_octets_per_byte (output_bfd),
+				     * bfd_octets_per_byte (output_bfd, NULL),
 				     size);
       free (buf);
       if (! ok)
@@ -11633,7 +11635,7 @@  elf_fixup_link_order (bfd *abfd, asection *o)
       s = sections[n]->u.indirect.section;
       mask = ~(bfd_vma) 0 << s->alignment_power;
       offset = (offset + ~mask) & mask;
-      s->output_offset = offset / bfd_octets_per_byte (abfd);
+      s->output_offset = offset / bfd_octets_per_byte (abfd, NULL);
       sections[n]->offset = offset;
       offset += sections[n]->size;
     }
@@ -12857,7 +12859,8 @@  bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
 	      if (! bfd_set_section_contents (abfd, o->output_section,
 					      o->contents,
 					      (file_ptr) o->output_offset
-					      * bfd_octets_per_byte (abfd),
+					      * bfd_octets_per_byte (abfd,
+								     NULL),
 					      o->size))
 		goto error_return;
 	    }
diff --git a/bfd/linker.c b/bfd/linker.c
index 382b69d8c3..b247cf589b 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -2402,7 +2402,7 @@  _bfd_generic_reloc_link_order (bfd *abfd,
 	     NULL, NULL, 0);
 	  break;
 	}
-      loc = link_order->offset * bfd_octets_per_byte (abfd);
+      loc = link_order->offset * bfd_octets_per_byte (abfd, sec);
       ok = bfd_set_section_contents (abfd, sec, buf, loc, size);
       free (buf);
       if (! ok)
@@ -2518,7 +2518,7 @@  default_data_link_order (bfd *abfd,
 	}
     }

-  loc = link_order->offset * bfd_octets_per_byte (abfd);
+  loc = link_order->offset * bfd_octets_per_byte (abfd, sec);
   result = bfd_set_section_contents (abfd, sec, fill, loc, size);

   if (fill != link_order->u.data.contents)
@@ -2655,7 +2655,8 @@  default_indirect_link_order (bfd *output_bfd,
     }

   /* Output the section contents.  */
-  loc = input_section->output_offset * bfd_octets_per_byte (output_bfd);
+  loc = (input_section->output_offset
+	 * bfd_octets_per_byte (output_bfd, output_section));
   if (! bfd_set_section_contents (output_bfd, output_section,
 				  new_contents, loc, input_section->size))
     goto error_return;
@@ -3099,7 +3100,7 @@  bfd_generic_define_common_symbol (bfd *output_bfd,

   /* Increase the size of the section to align the common symbol.
      The alignment must be a power of two.  */
-  alignment = bfd_octets_per_byte (output_bfd) << power_of_two;
+  alignment = bfd_octets_per_byte (output_bfd, section) << power_of_two;
   BFD_ASSERT (alignment != 0 && (alignment & -alignment) == alignment);
   section->size += alignment - 1;
   section->size &= -alignment;
diff --git a/bfd/reloc.c b/bfd/reloc.c
index ae71f6b005..f345cf6d3f 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -722,7 +722,7 @@  bfd_perform_relocation (bfd *abfd,
     return bfd_reloc_undefined;

   /* Is the address of the relocation really within the section?  */
-  octets = reloc_entry->address * bfd_octets_per_byte (abfd);
+  octets = reloc_entry->address * bfd_octets_per_byte (abfd, input_section);
   if (!bfd_reloc_offset_in_range (howto, abfd, input_section, octets))
     return bfd_reloc_outofrange;

@@ -744,7 +744,14 @@  bfd_perform_relocation (bfd *abfd,
   else
     output_base = reloc_target_output_section->vma;

-  relocation += output_base + symbol->section->output_offset;
+  /* For sections where relocations are in octets, output_base and
+     output_offset must also be converted to octets.  */
+  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+      && (symbol->section->flags & SEC_ELF_OCTETS))
+    relocation += ((output_base + symbol->section->output_offset)
+                   * bfd_octets_per_byte (abfd, NULL));
+  else
+    relocation += output_base + symbol->section->output_offset;

   /* Add in supplied addend.  */
   relocation += reloc_entry->addend;
@@ -1052,7 +1059,7 @@  bfd_install_relocation (bfd *abfd,
      it will have been checked in `bfd_perform_relocation already'.  */

   /* Is the address of the relocation really within the section?  */
-  octets = reloc_entry->address * bfd_octets_per_byte (abfd);
+  octets = reloc_entry->address * bfd_octets_per_byte (abfd, input_section);
   if (!bfd_reloc_offset_in_range (howto, abfd, input_section, octets))
     return bfd_reloc_outofrange;

@@ -1073,7 +1080,14 @@  bfd_install_relocation (bfd *abfd,
   else
     output_base = reloc_target_output_section->vma;

-  relocation += output_base + symbol->section->output_offset;
+  /* For sections where relocations are in octets, output_base and
+     output_offset must also be converted to octets.  */
+  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+      && (symbol->section->flags & SEC_ELF_OCTETS))
+    relocation += ((output_base + symbol->section->output_offset)
+		   * bfd_octets_per_byte (abfd, NULL));
+  else
+    relocation += output_base + symbol->section->output_offset;

   /* Add in supplied addend.  */
   relocation += reloc_entry->addend;
@@ -1337,7 +1351,8 @@  _bfd_final_link_relocate (reloc_howto_type *howto,
 			  bfd_vma addend)
 {
   bfd_vma relocation;
-  bfd_size_type octets = address * bfd_octets_per_byte (input_bfd);
+  bfd_size_type octets = (address
+			  * bfd_octets_per_byte (input_bfd, input_section));

   /* Sanity check the address.  */
   if (!bfd_reloc_offset_in_range (howto, input_bfd, input_section, octets))
@@ -1369,7 +1384,9 @@  _bfd_final_link_relocate (reloc_howto_type *howto,

   return _bfd_relocate_contents (howto, input_bfd, relocation,
 				 contents
-				 + address * bfd_octets_per_byte (input_bfd));
+				 + address
+				 * bfd_octets_per_byte (input_bfd,
+							input_section));
 }

 /* Relocate a given location using a given value and howto.  */
@@ -8363,7 +8380,8 @@  bfd_generic_get_relocated_section_contents (bfd *abfd,
 		= HOWTO (0, 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL,
 			 "unused", FALSE, 0, 0, FALSE);

-	      off = (*parent)->address * bfd_octets_per_byte (input_bfd);
+	      off = ((*parent)->address
+		     * bfd_octets_per_byte (input_bfd, input_section));
 	      _bfd_clear_contents ((*parent)->howto, input_bfd,
 				   input_section, data, off);
 	      (*parent)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
diff --git a/bfd/section.c b/bfd/section.c
index 34e08aef57..a7906e891a 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -351,6 +351,11 @@  CODE_FRAGMENT
 .  {* This section contains vliw code.  This is for Toshiba MeP only.  *}
 .#define SEC_MEP_VLIW               0x20000000
 .
+.  {* All symbols, sizes and relocations in this section are octets
+.     instead of bytes. Required for DWARF debug sections as DWARF
+.     information is organized in octets, not bytes. *}
+.#define SEC_ELF_OCTETS             0x40000000
+.
 .  {* Indicate that section has the no read flag set. This happens
 .     when memory read flag isn't set. *}
 .#define SEC_COFF_NOREAD            0x40000000
diff --git a/bfd/srec.c b/bfd/srec.c
index 218276837c..449d88c6b0 100644
--- a/bfd/srec.c
+++ b/bfd/srec.c
@@ -885,7 +885,7 @@  srec_set_section_contents (bfd *abfd,
 			   file_ptr offset,
 			   bfd_size_type bytes_to_do)
 {
-  int opb = bfd_octets_per_byte (abfd);
+  int opb = bfd_octets_per_byte (abfd, NULL);
   tdata_type *tdata = abfd->tdata.srec_data;
   srec_data_list_type *entry;

@@ -1053,7 +1053,8 @@  srec_write_section (bfd *abfd,
       if (octets_this_chunk > _bfd_srec_len)
 	octets_this_chunk = _bfd_srec_len;

-      address = list->where + octets_written / bfd_octets_per_byte (abfd);
+      address = list->where + (octets_written
+			       / bfd_octets_per_byte (abfd, NULL));

       if (! srec_write_record (abfd,
 			       tdata->type,
diff --git a/bfd/syms.c b/bfd/syms.c
index 146f674a13..ec7d2c8dba 100644
--- a/bfd/syms.c
+++ b/bfd/syms.c
@@ -1090,7 +1090,8 @@  _bfd_stab_section_find_nearest_line (bfd *abfd,
 		  || r->howto->pc_relative
 		  || r->howto->bitpos != 0
 		  || r->howto->dst_mask != 0xffffffff
-		  || r->address * bfd_octets_per_byte (abfd) + 4 > stabsize)
+		  || (r->address * bfd_octets_per_byte (abfd, NULL) + 4
+		      > stabsize))
 		{
 		  _bfd_error_handler
 		    (_("unsupported .stab relocation"));
@@ -1101,12 +1102,13 @@  _bfd_stab_section_find_nearest_line (bfd *abfd,
 		}

 	      val = bfd_get_32 (abfd, info->stabs
-				+ r->address * bfd_octets_per_byte (abfd));
+				+ (r->address
+				   * bfd_octets_per_byte (abfd, NULL)));
 	      val &= r->howto->src_mask;
 	      sym = *r->sym_ptr_ptr;
 	      val += sym->value + sym->section->vma + r->addend;
 	      bfd_put_32 (abfd, (bfd_vma) val, info->stabs
-			  + r->address * bfd_octets_per_byte (abfd));
+			  + r->address * bfd_octets_per_byte (abfd, NULL));
 	    }
 	}