Factor out common relocation processing

This patch factors out some code common to both bfd_perform_relocation
and bfd_install_relocation, in the process fixing the omission of
"case -1" in bfd_install_relocation.

	* reloc.c (bfd_get_reloc_size): Sort switch.
	(read_reloc, write_reloc, apply_reloc): New functions.
	(bfd_perform_relocation, bfd_install_relocation): Use apply_reloc.
	(_bfd_relocate_contents): Use read_reloc and write_reloc.
	(_bfd_clear_contents): Likewise.
This commit is contained in:
Alan Modra 2018-08-11 11:07:07 +09:30
parent 7cf9ebc695
commit 1dc9e2d63e
2 changed files with 116 additions and 244 deletions

View File

@ -1,3 +1,11 @@
2018-08-11 Alan Modra <amodra@gmail.com>
* reloc.c (bfd_get_reloc_size): Sort switch.
(read_reloc, write_reloc, apply_reloc): New functions.
(bfd_perform_relocation, bfd_install_relocation): Use apply_reloc.
(_bfd_relocate_contents): Use read_reloc and write_reloc.
(_bfd_clear_contents): Likewise.
2018-08-11 John Darrington <john@darrington.wattle.id.au>
* reloc.c (_bfd_relocate_contents): Handle 3 byte relocs.

View File

@ -431,15 +431,15 @@ bfd_get_reloc_size (reloc_howto_type *howto)
{
switch (howto->size)
{
case 5: return 3;
case 0: return 1;
case 1: return 2;
case 2: return 4;
case 1:
case -1: return 2;
case 2:
case -2: return 4;
case 3: return 0;
case 4: return 8;
case 5: return 3;
case 8: return 16;
case -1: return 2;
case -2: return 4;
default: abort ();
}
}
@ -574,6 +574,100 @@ bfd_reloc_offset_in_range (reloc_howto_type *howto,
return octet <= octet_end && octet + reloc_size <= octet_end;
}
/* Read and return the section contents at DATA converted to a host
integer (bfd_vma). The number of bytes read is given by the HOWTO. */
static bfd_vma
read_reloc (bfd *abfd, bfd_byte *data, reloc_howto_type *howto)
{
switch (howto->size)
{
case 0:
return bfd_get_8 (abfd, data);
case 1:
case -1:
return bfd_get_16 (abfd, data);
case 2:
case -2:
return bfd_get_32 (abfd, data);
case 3:
break;
#ifdef BFD64
case 4:
return bfd_get_64 (abfd, data);
#endif
case 5:
return bfd_get_24 (abfd, data);
default:
abort ();
}
return 0;
}
/* Convert VAL to target format and write to DATA. The number of
bytes written is given by the HOWTO. */
static void
write_reloc (bfd *abfd, bfd_vma val, bfd_byte *data, reloc_howto_type *howto)
{
switch (howto->size)
{
case 0:
bfd_put_8 (abfd, val, data);
break;
case 1:
case -1:
bfd_put_16 (abfd, val, data);
break;
case 2:
case -2:
bfd_put_32 (abfd, val, data);
break;
case 3:
break;
#ifdef BFD64
case 4:
bfd_put_64 (abfd, val, data);
break;
#endif
case 5:
bfd_put_24 (abfd, val, data);
break;
default:
abort ();
}
}
/* Apply RELOCATION value to target bytes at DATA, according to
HOWTO. */
static void
apply_reloc (bfd *abfd, bfd_byte *data, reloc_howto_type *howto,
bfd_vma relocation)
{
bfd_vma val = read_reloc (abfd, data, howto);
if (howto->size < 0)
relocation = -relocation;
val = ((val & ~howto->dst_mask)
| (((val & howto->src_mask) + relocation) & howto->dst_mask));
write_reloc (abfd, val, data, howto);
}
/*
FUNCTION
bfd_perform_relocation
@ -913,78 +1007,8 @@ space consuming. For each target:
= R R R R R R R R R R put into bfd_put<size>
*/
#define DOIT(x) \
x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask))
switch (howto->size)
{
case 5:
{
long x = bfd_get_24 (abfd, (bfd_byte *) data + octets);
DOIT (x);
bfd_put_24 (abfd, (bfd_vma) x, (unsigned char *) data + octets);
}
break;
case 0:
{
char x = bfd_get_8 (abfd, (char *) data + octets);
DOIT (x);
bfd_put_8 (abfd, x, (unsigned char *) data + octets);
}
break;
case 1:
{
short x = bfd_get_16 (abfd, (bfd_byte *) data + octets);
DOIT (x);
bfd_put_16 (abfd, (bfd_vma) x, (unsigned char *) data + octets);
}
break;
case 2:
{
long x = bfd_get_32 (abfd, (bfd_byte *) data + octets);
DOIT (x);
bfd_put_32 (abfd, (bfd_vma) x, (bfd_byte *) data + octets);
}
break;
case -2:
{
long x = bfd_get_32 (abfd, (bfd_byte *) data + octets);
relocation = -relocation;
DOIT (x);
bfd_put_32 (abfd, (bfd_vma) x, (bfd_byte *) data + octets);
}
break;
case -1:
{
long x = bfd_get_16 (abfd, (bfd_byte *) data + octets);
relocation = -relocation;
DOIT (x);
bfd_put_16 (abfd, (bfd_vma) x, (bfd_byte *) data + octets);
}
break;
case 3:
/* Do nothing */
break;
case 4:
#ifdef BFD64
{
bfd_vma x = bfd_get_64 (abfd, (bfd_byte *) data + octets);
DOIT (x);
bfd_put_64 (abfd, x, (bfd_byte *) data + octets);
}
#else
abort ();
#endif
break;
default:
return bfd_reloc_other;
}
data = (bfd_byte *) data + octets;
apply_reloc (abfd, data, howto, relocation);
return flag;
}
@ -1309,66 +1333,8 @@ space consuming. For each target:
= R R R R R R R R R R put into bfd_put<size>
*/
#define DOIT(x) \
x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask))
data = (bfd_byte *) data_start + (octets - data_start_offset);
switch (howto->size)
{
case 0:
{
char x = bfd_get_8 (abfd, data);
DOIT (x);
bfd_put_8 (abfd, x, data);
}
break;
case 1:
{
short x = bfd_get_16 (abfd, data);
DOIT (x);
bfd_put_16 (abfd, (bfd_vma) x, data);
}
break;
case 2:
{
long x = bfd_get_32 (abfd, data);
DOIT (x);
bfd_put_32 (abfd, (bfd_vma) x, data);
}
break;
case 5:
{
long x = bfd_get_24 (abfd, data);
DOIT (x);
bfd_put_24 (abfd, (bfd_vma) x, data);
}
break;
case -2:
{
long x = bfd_get_32 (abfd, data);
relocation = -relocation;
DOIT (x);
bfd_put_32 (abfd, (bfd_vma) x, data);
}
break;
case 3:
/* Do nothing */
break;
case 4:
{
bfd_vma x = bfd_get_64 (abfd, data);
DOIT (x);
bfd_put_64 (abfd, x, data);
}
break;
default:
return bfd_reloc_other;
}
apply_reloc (abfd, data, howto, relocation);
return flag;
}
@ -1447,8 +1413,7 @@ _bfd_relocate_contents (reloc_howto_type *howto,
bfd_vma relocation,
bfd_byte *location)
{
int size;
bfd_vma x = 0;
bfd_vma x;
bfd_reloc_status_type flag;
unsigned int rightshift = howto->rightshift;
unsigned int bitpos = howto->bitpos;
@ -1459,33 +1424,7 @@ _bfd_relocate_contents (reloc_howto_type *howto,
relocation = -relocation;
/* Get the value we are going to relocate. */
size = bfd_get_reloc_size (howto);
switch (size)
{
default:
abort ();
case 0:
return bfd_reloc_ok;
case 1:
x = bfd_get_8 (input_bfd, location);
break;
case 2:
x = bfd_get_16 (input_bfd, location);
break;
case 3:
x = bfd_get_24 (input_bfd, location);
break;
case 4:
x = bfd_get_32 (input_bfd, location);
break;
case 8:
#ifdef BFD64
x = bfd_get_64 (input_bfd, location);
#else
abort ();
#endif
break;
}
x = read_reloc (input_bfd, location, howto);
/* Check for overflow. FIXME: We may drop bits during the addition
which we don't check for. We must either check at every single
@ -1591,31 +1530,7 @@ _bfd_relocate_contents (reloc_howto_type *howto,
| (((x & howto->src_mask) + relocation) & howto->dst_mask));
/* Put the relocated value back in the object file. */
switch (size)
{
default:
abort ();
case 1:
bfd_put_8 (input_bfd, x, location);
break;
case 2:
bfd_put_16 (input_bfd, x, location);
break;
case 3:
bfd_put_24 (input_bfd, x, location);
break;
case 4:
bfd_put_32 (input_bfd, x, location);
break;
case 8:
#ifdef BFD64
bfd_put_64 (input_bfd, x, location);
#else
abort ();
#endif
break;
}
write_reloc (input_bfd, x, location, howto);
return flag;
}
@ -1630,37 +1545,10 @@ _bfd_clear_contents (reloc_howto_type *howto,
asection *input_section,
bfd_byte *location)
{
int size;
bfd_vma x = 0;
bfd_vma x;
/* Get the value we are going to relocate. */
size = bfd_get_reloc_size (howto);
switch (size)
{
default:
abort ();
case 0:
return;
case 1:
x = bfd_get_8 (input_bfd, location);
break;
case 2:
x = bfd_get_16 (input_bfd, location);
break;
case 3:
x = bfd_get_24 (input_bfd, location);
break;
case 4:
x = bfd_get_32 (input_bfd, location);
break;
case 8:
#ifdef BFD64
x = bfd_get_64 (input_bfd, location);
#else
abort ();
#endif
break;
}
x = read_reloc (input_bfd, location, howto);
/* Zero out the unwanted bits of X. */
x &= ~howto->dst_mask;
@ -1673,31 +1561,7 @@ _bfd_clear_contents (reloc_howto_type *howto,
x |= 1;
/* Put the relocated value back in the object file. */
switch (size)
{
default:
case 0:
abort ();
case 1:
bfd_put_8 (input_bfd, x, location);
break;
case 2:
bfd_put_16 (input_bfd, x, location);
break;
case 3:
bfd_put_24 (input_bfd, x, location);
break;
case 4:
bfd_put_32 (input_bfd, x, location);
break;
case 8:
#ifdef BFD64
bfd_put_64 (input_bfd, x, location);
#else
abort ();
#endif
break;
}
write_reloc (input_bfd, x, location, howto);
}
/*