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.
This commit is contained in:
Alan Modra
2020-08-25 14:05:10 +09:30
parent b8ff233b54
commit d2327e47ef
2 changed files with 28 additions and 35 deletions

View File

@ -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> 2020-08-25 Alan Modra <amodra@gmail.com>
PR 26419 PR 26419

View File

@ -10348,16 +10348,22 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
if (globals->use_rel) 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; case 0: addend = bfd_get_8 (input_bfd, hit_data); break;
signed_addend &= ~ howto->src_mask; case 1: addend = bfd_get_16 (input_bfd, hit_data); break;
signed_addend |= addend; case 2: addend = bfd_get_32 (input_bfd, hit_data); break;
default: addend = 0; break;
} }
else /* Note: the addend and signed_addend calculated here are
signed_addend = addend; 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 else
addend = signed_addend = rel->r_addend; addend = signed_addend = rel->r_addend;
@ -10752,10 +10758,6 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
value -= (input_section->output_section->vma value -= (input_section->output_section->vma
+ input_section->output_offset); + input_section->output_offset);
value -= rel->r_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 = value;
@ -10860,9 +10862,6 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
return bfd_reloc_ok; return bfd_reloc_ok;
case R_ARM_ABS8: 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; value += addend;
/* There is no way to tell whether the user intended to use a signed or /* 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; return bfd_reloc_ok;
case R_ARM_ABS16: 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; value += addend;
/* See comment for R_ARM_ABS8. */ /* See comment for R_ARM_ABS8. */
@ -11356,25 +11352,12 @@ elf32_arm_final_link_relocate (reloc_howto_type * howto,
/* CZB cannot jump backward. */ /* CZB cannot jump backward. */
if (r_type == R_ARM_THM_JUMP6) if (r_type == R_ARM_THM_JUMP6)
{
reloc_signed_min = 0; reloc_signed_min = 0;
if (globals->use_rel) if (globals->use_rel)
{ signed_addend = ((addend & 0x200) >> 3) | ((addend & 0xf8) >> 2);
/* 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;
} }
relocation = value + signed_addend; relocation = value + signed_addend;
relocation -= (input_section->output_section->vma relocation -= (input_section->output_section->vma