[binutils-gdb] PR26422, ASAN: elf32_arm_final_link_relocate elf32-arm.c:10351

Alan Modra amodra@sourceware.org
Tue Aug 25 13:38:00 GMT 2020


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d2327e47ef26dc88192e07b53cbad0b768cecf2e

commit d2327e47ef26dc88192e07b53cbad0b768cecf2e
Author: Alan Modra <amodra@gmail.com>
Date:   Tue Aug 25 14:05:10 2020 +0930

    PR26422, ASAN: elf32_arm_final_link_relocate elf32-arm.c:10351
    
    Always reading 32 bits in order to extract addends from instruction
    fields is wrong when the field size is smaller.  It also leads to
    reading past the end of the section.  This patch tidies that by
    reading the proper field size, which allows some later refetching of
    addends to disappear.
    
            PR 26422
            * elf32-arm.c (elf32_arm_final_link_relocate): Use the appropriate
            bfd_get_x size function to read addends out of fields.  Apply
            rightshift adjustment too.  Don't apply the now unnecessary
            howto->size shift to branch REL addends.  Don't refetch R_ARM_ABS8
            and R_ARM_ABS16 addends.  Don't refetch thumb branch addends.
            Correct R_ARM_THM_JUMP6 addend.

Diff:
---
 bfd/ChangeLog   | 10 ++++++++++
 bfd/elf32-arm.c | 53 ++++++++++++++++++-----------------------------------
 2 files changed, 28 insertions(+), 35 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index f1f0e322fe1..a24957a8c19 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,13 @@
+2020-08-25  Alan Modra  <amodra@gmail.com>
+
+	PR 26422
+	* elf32-arm.c (elf32_arm_final_link_relocate): Use the appropriate
+	bfd_get_x size function to read addends out of fields.  Apply
+	rightshift adjustment too.  Don't apply the now unnecessary
+	howto->size shift to branch REL addends.  Don't refetch R_ARM_ABS8
+	and R_ARM_ABS16 addends.  Don't refetch thumb branch addends.
+	Correct R_ARM_THM_JUMP6 addend.
+
 2020-08-25  Alan Modra  <amodra@gmail.com>
 
 	PR 26419
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 66930c0c7dc..8fec76e4e1d 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -10348,16 +10348,22 @@ elf32_arm_final_link_relocate (reloc_howto_type *	    howto,
 
   if (globals->use_rel)
     {
-      addend = bfd_get_32 (input_bfd, hit_data) & howto->src_mask;
+      bfd_vma sign;
 
-      if (addend & ((howto->src_mask + 1) >> 1))
+      switch (howto->size)
 	{
-	  signed_addend = -1;
-	  signed_addend &= ~ howto->src_mask;
-	  signed_addend |= addend;
+	case 0: addend = bfd_get_8 (input_bfd, hit_data); break;
+	case 1: addend = bfd_get_16 (input_bfd, hit_data); break;
+	case 2: addend = bfd_get_32 (input_bfd, hit_data); break;
+	default: addend = 0; break;
 	}
-      else
-	signed_addend = addend;
+      /* Note: the addend and signed_addend calculated here are
+	 incorrect for any split field.  */
+      addend &= howto->src_mask;
+      sign = howto->src_mask & ~(howto->src_mask >> 1);
+      signed_addend = (addend ^ sign) - sign;
+      signed_addend = (bfd_vma) signed_addend << howto->rightshift;
+      addend <<= howto->rightshift;
     }
   else
     addend = signed_addend = rel->r_addend;
@@ -10752,11 +10758,7 @@ elf32_arm_final_link_relocate (reloc_howto_type *	    howto,
 	  value -= (input_section->output_section->vma
 		    + input_section->output_offset);
 	  value -= rel->r_offset;
-	  if (globals->use_rel)
-	    value += (signed_addend << howto->size);
-	  else
-	    /* RELA addends do not have to be adjusted by howto->size.  */
-	    value += signed_addend;
+	  value += signed_addend;
 
 	  signed_addend = value;
 	  signed_addend >>= howto->rightshift;
@@ -10860,9 +10862,6 @@ elf32_arm_final_link_relocate (reloc_howto_type *	    howto,
       return bfd_reloc_ok;
 
     case R_ARM_ABS8:
-      /* PR 16202: Refectch the addend using the correct size.  */
-      if (globals->use_rel)
-	addend = bfd_get_8 (input_bfd, hit_data);
       value += addend;
 
       /* There is no way to tell whether the user intended to use a signed or
@@ -10875,9 +10874,6 @@ elf32_arm_final_link_relocate (reloc_howto_type *	    howto,
       return bfd_reloc_ok;
 
     case R_ARM_ABS16:
-      /* PR 16202: Refectch the addend using the correct size.  */
-      if (globals->use_rel)
-	addend = bfd_get_16 (input_bfd, hit_data);
       value += addend;
 
       /* See comment for R_ARM_ABS8.  */
@@ -11356,25 +11352,12 @@ elf32_arm_final_link_relocate (reloc_howto_type *	    howto,
 
 	/* CZB cannot jump backward.  */
 	if (r_type == R_ARM_THM_JUMP6)
-	  reloc_signed_min = 0;
-
-	if (globals->use_rel)
 	  {
-	    /* Need to refetch addend.  */
-	    addend = bfd_get_16 (input_bfd, hit_data) & howto->src_mask;
-	    if (addend & ((howto->src_mask + 1) >> 1))
-	      {
-		signed_addend = -1;
-		signed_addend &= ~ howto->src_mask;
-		signed_addend |= addend;
-	      }
-	    else
-	      signed_addend = addend;
-	    /* The value in the insn has been right shifted.  We need to
-	       undo this, so that we can perform the address calculation
-	       in terms of bytes.  */
-	    signed_addend <<= howto->rightshift;
+	    reloc_signed_min = 0;
+	    if (globals->use_rel)
+	      signed_addend = ((addend & 0x200) >> 3) | ((addend & 0xf8) >> 2);
 	  }
+
 	relocation = value + signed_addend;
 
 	relocation -= (input_section->output_section->vma


More information about the Binutils-cvs mailing list