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

Message ID 20191116232130.14278-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. 16, 2019, 11:21 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.
	* bfd-in2.h: Regenerate.
	* elf.c (_bfd_elf_make_section_from_shdr): Set SEC_ELF_OCTETS
	for sections with names .gnu.build.attributes, .debug*,
	.zdebug* and .note.gnu*.
	* archures.c (bfd_section_octets_per_byte): New function.
	* binary.c (binary_set_section_contents): Call
	bfd_section_octets_per_byte() for each section.
	* linker.c (_bfd_generic_reloc_link_order): Use
	bfd_section_octets_per_byte() instead of bfd_octets_per_byte().
	(default_data_link_order): Likewise.
	(default_indirect_link_order): Likewise.
	(bfd_generic_define_common_symbol): Likewise. Set ATTRIBUTE_UNUSED
	for argument argument output_bfd.
	* reloc.c (bfd_perform_relocation): Use
	bfd_section_octets_per_byte() instead of bfd_octets_per_byte().
	For section which have SEC_ELF_OCTETS set, multiply output_base
	and output_offset with bfd_octets_per_byte().
	(bfd_install_relocation): Likewise.
	(_bfd_final_link_relocate): Use bfd_section_octets_per_byte().
	(bfd_generic_get_relocated_section_contents): Likewise.

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

---
 bfd/archures.c | 27 +++++++++++++++++++++++++++
 bfd/bfd-in2.h  |  8 ++++++++
 bfd/binary.c   |  4 ++--
 bfd/elf.c      |  9 +++++++++
 bfd/linker.c   | 11 ++++++-----
 bfd/reloc.c    | 30 +++++++++++++++++++++++-------
 bfd/section.c  |  5 +++++
 7 files changed, 80 insertions(+), 14 deletions(-)

--
2.16.4

Comments

Alan Modra Nov. 19, 2019, 10 p.m. | #1
On Sun, Nov 17, 2019 at 12:21:27AM +0100, Christian Eggers wrote:
> +unsigned int

> +bfd_section_octets_per_byte (const asection *sec)

> +{

> +  unsigned int opb = bfd_octets_per_byte (sec->owner);


If sec can be be the absolute section (and I think it can) then
sec->owner will be NULL and this will segfault.  Instead of adding a
new function, I think you'd be better off adding a section parameter
to bfd_octets_per_byte and allow it to be NULL.  This will also force
you to at least look at all current uses of bfd_octets_per_byte and
perhaps see other places where you want the semantics of your new
function.

Some style nits need fixing.  There are repeated occurrences of the
following in the whole series.

> -  loc = input_section->output_offset * bfd_octets_per_byte (output_bfd);

> +  loc = input_section->output_offset

> +        * bfd_section_octets_per_byte (output_section);


Add extra parens here so that auto-formatting tools indent correctly:
  loc = (input_section->output_offset
	 * bfd_section_octets_per_byte (output_section));
Also indent with tabs.

> +  /* For sections where relocations are in octets, output_base and output_offset

> +   * must also be converted to octets. */


Comment style is wrong.  We don't do comment blocks with asterisks
down the left.  Also, two spaces after a full stop.

> +  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);


No operators at end of line.  '&&' and '*' belong on the next line.

-- 
Alan Modra
Australia Development Lab, IBM
Christian Eggers Nov. 21, 2019, 9:10 p.m. | #2
Am Dienstag, 19. November 2019, 23:00:30 CET schrieben Sie:
> On Sun, Nov 17, 2019 at 12:21:27AM +0100, Christian Eggers wrote:

> > +unsigned int

> > +bfd_section_octets_per_byte (const asection *sec)

> > +{

> > +  unsigned int opb = bfd_octets_per_byte (sec->owner);

>

> If sec can be be the absolute section (and I think it can) then

> sec->owner will be NULL and this will segfault.  Instead of adding a

> new function, I think you'd be better off adding a section parameter

> to bfd_octets_per_byte and allow it to be NULL.  This will also force

> you to at least look at all current uses of bfd_octets_per_byte and

> perhaps see other places where you want the semantics of your new

> function.


In v2 I have removed the new function and added the section parameter
to bfd_octets_per_byte().

I would like to avoid adding a non NULL section parameter at further calls of
to bfd_octets_per_byte(), because this would probably not be hit by the
testsuite of my architecture. For instance I use the generic linker, so
changes in the ELF linker would not be tested.

Maybe the calls to bfd_octets_per_byte() should be removed from platform
specific files (e.g. arm, i386, mips, ...) where the number of octets is
always one (may improve readability).

> Some style nits need fixing.  There are repeated occurrences of the

> following in the whole series.

> [...]


I've tried my best to solve these issues in v2. Perhaps these problem could be
avoided if there were a guide like "sending-patches"...

regards
Christian

Patch

diff --git a/bfd/archures.c b/bfd/archures.c
index 569876eed0..c949c1a789 100644
--- a/bfd/archures.c
+++ b/bfd/archures.c
@@ -1374,6 +1374,33 @@  bfd_printable_arch_mach (enum bfd_architecture arch, unsigned long machine)
   return "UNKNOWN!";
 }

+/*
+FUNCTION
+	bfd_section_octets_per_byte
+
+SYNOPSIS
+	unsigned int bfd_section_octets_per_byte (const asection *sec);
+
+DESCRIPTION
+	Return the number of octets (8-bit quantities) per target byte
+	(minimum addressable unit) for a particular section. A target can use
+	more than one octet per byte for normal sections (like ".text", ".data"
+	or ".bss), but nevertheless use only one octet per byte for special
+	sections like ".(z)debug*" or ".gnu.build.attributes".
+*/
+
+unsigned int
+bfd_section_octets_per_byte (const asection *sec)
+{
+  unsigned int opb = bfd_octets_per_byte (sec->owner);
+
+  if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour &&
+      sec && (sec->flags & SEC_ELF_OCTETS))
+    opb = 1;
+
+  return opb;
+}
+
 /*
 FUNCTION
 	bfd_octets_per_byte
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 3244905b45..714a4dd423 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,6 +1998,9 @@  const bfd_arch_info_type *bfd_lookup_arch
 const char *bfd_printable_arch_mach
    (enum bfd_architecture arch, unsigned long machine);

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

 unsigned int bfd_arch_mach_octets_per_byte
diff --git a/bfd/binary.c b/bfd/binary.c
index eb87d11b6e..c0cd0852ba 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_section_octets_per_byte (s);
+
 	  s->filepos = (s->lma - low) * opb;

 	  /* Skip following warning check for sections that will not
diff --git a/bfd/elf.c b/bfd/elf.c
index be060d579c..21e734f95e 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;
+	    }
 	}
     }

diff --git a/bfd/linker.c b/bfd/linker.c
index 382b69d8c3..533ef361cb 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_section_octets_per_byte (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_section_octets_per_byte (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_section_octets_per_byte (output_section);
   if (! bfd_set_section_contents (output_bfd, output_section,
 				  new_contents, loc, input_section->size))
     goto error_return;
@@ -3083,7 +3084,7 @@  DESCRIPTION
 */

 bfd_boolean
-bfd_generic_define_common_symbol (bfd *output_bfd,
+bfd_generic_define_common_symbol (bfd *output_bfd ATTRIBUTE_UNUSED,
 				  struct bfd_link_info *info ATTRIBUTE_UNUSED,
 				  struct bfd_link_hash_entry *h)
 {
@@ -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_section_octets_per_byte (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..534b47b459 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_section_octets_per_byte (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);
+  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_section_octets_per_byte (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);
+  else
+    relocation += output_base + symbol->section->output_offset;

   /* Add in supplied addend.  */
   relocation += reloc_entry->addend;
@@ -1337,7 +1351,7 @@  _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_section_octets_per_byte (input_section);

   /* Sanity check the address.  */
   if (!bfd_reloc_offset_in_range (howto, input_bfd, input_section, octets))
@@ -1369,7 +1383,8 @@  _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_section_octets_per_byte (
+				     input_section));
 }

 /* Relocate a given location using a given value and howto.  */
@@ -8363,7 +8378,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_section_octets_per_byte (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