[PATCH] bfd: Fix 64-bit relocation handling for a.out

Gunther Nikl gnikl@justmail.de
Mon Apr 27 19:16:03 GMT 2020
Hello!

The a.out backend has experimental code for 64-bit relocation types when
using standard relocations. The size of an relocation entry is encoded as
a power of two value for this relocation type in the external relocation
structure. The size values specified in howto_table_std for 8, 16 and 32
bit relocations match that requirement. However, 64-bit relocations use
4 as size value since the value 3 was already taken as size value for
howtos with a non-zero special function. Initially the size value used
for 64-bit relocations in aoutx.h was 3 but this got changed in 1993 by
Ken Raeburn to use the value agreed upon.
This patch uses bfd_get_reloc_size to query the real relocation size and
maps 8 to 3. The handling of smaller relocation types is kept as-is.


Regards,
Gunther Nikl

2020-04-XX  Gunther Nikl  <gnikl@justmail.de>

	* aoutx.h (NAME (aout, swap_std_reloc_out)): Special case 64 bit
	relocations.
	(aout_link_reloc_link_order): Likewise. Make r_length an unsigned.

diff --git a/bfd/aoutx.h b/bfd/aoutx.h
index 41ced3dc72..b7f1a42de9 100644
--- a/bfd/aoutx.h
+++ b/bfd/aoutx.h
@@ -1945,7 +1945,10 @@ NAME (aout, swap_std_reloc_out) (bfd *abfd,
   PUT_WORD (abfd, g->address, natptr->r_address);
 
   BFD_ASSERT (g->howto != NULL);
-  r_length = g->howto->size ;	/* Size as a power of two.  */
+  if (bfd_get_reloc_size (g->howto) != 8)
+    r_length = g->howto->size;	/* Size as a power of two.  */
+  else
+    r_length = 3;
   r_pcrel  = (int) g->howto->pc_relative; /* Relative to PC?  */
   /* XXX This relies on relocs coming from a.out files.  */
   r_baserel = (g->howto->type & 8) != 0;
@@ -3803,13 +3806,16 @@ aout_link_reloc_link_order (struct aout_final_link_info *flaginfo,
 	int r_baserel;
 	int r_jmptable;
 	int r_relative;
-	int r_length;
+	unsigned int r_length;
 
 	r_pcrel = (int) howto->pc_relative;
 	r_baserel = (howto->type & 8) != 0;
 	r_jmptable = (howto->type & 16) != 0;
 	r_relative = (howto->type & 32) != 0;
-	r_length = howto->size;
+	if (bfd_get_reloc_size (howto) != 8)
+	  r_length = howto->size;	/* Size as a power of two.  */
+	else
+	  r_length = 3;
 
 	PUT_WORD (flaginfo->output_bfd, p->offset, srel.r_address);
 	if (bfd_header_big_endian (flaginfo->output_bfd))


More information about the Binutils mailing list