PR28163, Segment fault in function rl78_special_reloc
Relocation offset checks were completely missing in the rl78 backend, allowing a relocation to write over memory anywhere. This was true for rl78_special_reloc, a function primarily used when applying debug relocations, and in rl78_elf_relocate_section used by the linker. This patch fixes those problems by correcting inaccuracies in the relocation howtos, then uses those howtos to sanity check relocation offsets before applying relocations. In addition, the patch implements overflow checking using the howto information rather than the ad-hoc scheme implemented in relocate_section. I implemented the overflow checking in rl78_special_reloc too. * elf32-rl78.c (RL78REL, RL78_OP_REL): Add mask parameter. (rl78_elf_howto_table): Set destination masks. Correct size and bitsize of DIR32_REV. Correct complain_on_overflow for many relocs as per tests in relocate_section. Add RH_SFR. Correct bitsize for RH_SADDR. Set size to 3 and bitsize to 0 for all OP relocs. (check_overflow): New function. (rl78_special_reloc): Check that reloc address is within section. Apply relocations using reloc howto. Check for overflow. (RANGE): Delete. (rl78_elf_relocate_section): Sanity check r_offset. Perform overflow checking using reloc howto.
This commit is contained in:
parent
c0e94211e1
commit
2ad55ffca1
1 changed files with 325 additions and 330 deletions
279
bfd/elf32-rl78.c
279
bfd/elf32-rl78.c
|
@ -27,17 +27,16 @@
|
||||||
|
|
||||||
#define valid_16bit_address(v) ((v) <= 0x0ffff || (v) >= 0xf0000)
|
#define valid_16bit_address(v) ((v) <= 0x0ffff || (v) >= 0xf0000)
|
||||||
|
|
||||||
#define RL78REL(n,sz,bit,shift,complain,pcrel) \
|
#define RL78REL(n,sz,bit,mask,shift,complain,pcrel) \
|
||||||
HOWTO (R_RL78_##n, shift, sz, bit, pcrel, 0, complain_overflow_ ## complain, \
|
HOWTO (R_RL78_##n, shift, sz, bit, pcrel, 0, complain_overflow_ ## complain, \
|
||||||
bfd_elf_generic_reloc, "R_RL78_" #n, false, 0, ~0, false)
|
bfd_elf_generic_reloc, "R_RL78_" #n, false, 0, mask, false)
|
||||||
|
|
||||||
static bfd_reloc_status_type rl78_special_reloc (bfd *, arelent *, asymbol *, void *,
|
static bfd_reloc_status_type rl78_special_reloc (bfd *, arelent *, asymbol *, void *,
|
||||||
asection *, bfd *, char **);
|
asection *, bfd *, char **);
|
||||||
|
|
||||||
/* FIXME: We could omit the SHIFT parameter, it is always zero. */
|
#define RL78_OP_REL(n,sz,bit,mask,shift,complain,pcrel) \
|
||||||
#define RL78_OP_REL(n,sz,bit,shift,complain,pcrel) \
|
|
||||||
HOWTO (R_RL78_##n, shift, sz, bit, pcrel, 0, complain_overflow_ ## complain, \
|
HOWTO (R_RL78_##n, shift, sz, bit, pcrel, 0, complain_overflow_ ## complain, \
|
||||||
rl78_special_reloc, "R_RL78_" #n, false, 0, ~0, false)
|
rl78_special_reloc, "R_RL78_" #n, false, 0, mask, false)
|
||||||
|
|
||||||
/* Note that the relocations around 0x7f are internal to this file;
|
/* Note that the relocations around 0x7f are internal to this file;
|
||||||
feel free to move them as needed to avoid conflicts with published
|
feel free to move them as needed to avoid conflicts with published
|
||||||
|
@ -45,25 +44,25 @@ static bfd_reloc_status_type rl78_special_reloc (bfd *, arelent *, asymbol *, vo
|
||||||
|
|
||||||
static reloc_howto_type rl78_elf_howto_table [] =
|
static reloc_howto_type rl78_elf_howto_table [] =
|
||||||
{
|
{
|
||||||
RL78REL (NONE, 3, 0, 0, dont, false),
|
RL78REL (NONE, 3, 0, 0, 0, dont, false),
|
||||||
RL78REL (DIR32, 2, 32, 0, signed, false),
|
RL78REL (DIR32, 2, 32, 0xffffffff, 0, dont, false),
|
||||||
RL78REL (DIR24S, 2, 24, 0, signed, false),
|
RL78REL (DIR24S, 2, 24, 0xffffff, 0, signed, false),
|
||||||
RL78REL (DIR16, 1, 16, 0, dont, false),
|
RL78REL (DIR16, 1, 16, 0xffff, 0, bitfield, false),
|
||||||
RL78REL (DIR16U, 1, 16, 0, unsigned, false),
|
RL78REL (DIR16U, 1, 16, 0xffff, 0, unsigned, false),
|
||||||
RL78REL (DIR16S, 1, 16, 0, signed, false),
|
RL78REL (DIR16S, 1, 16, 0xffff, 0, bitfield, false),
|
||||||
RL78REL (DIR8, 0, 8, 0, dont, false),
|
RL78REL (DIR8, 0, 8, 0xff, 0, dont, false),
|
||||||
RL78REL (DIR8U, 0, 8, 0, unsigned, false),
|
RL78REL (DIR8U, 0, 8, 0xff, 0, unsigned, false),
|
||||||
RL78REL (DIR8S, 0, 8, 0, signed, false),
|
RL78REL (DIR8S, 0, 8, 0xff, 0, bitfield, false),
|
||||||
RL78REL (DIR24S_PCREL, 2, 24, 0, signed, true),
|
RL78REL (DIR24S_PCREL, 2, 24, 0xffffff, 0, signed, true),
|
||||||
RL78REL (DIR16S_PCREL, 1, 16, 0, signed, true),
|
RL78REL (DIR16S_PCREL, 1, 16, 0xffff, 0, signed, true),
|
||||||
RL78REL (DIR8S_PCREL, 0, 8, 0, signed, true),
|
RL78REL (DIR8S_PCREL, 0, 8, 0xff, 0, signed, true),
|
||||||
RL78REL (DIR16UL, 1, 16, 2, unsigned, false),
|
RL78REL (DIR16UL, 1, 16, 0xffff, 2, unsigned, false),
|
||||||
RL78REL (DIR16UW, 1, 16, 1, unsigned, false),
|
RL78REL (DIR16UW, 1, 16, 0xffff, 1, unsigned, false),
|
||||||
RL78REL (DIR8UL, 0, 8, 2, unsigned, false),
|
RL78REL (DIR8UL, 0, 8, 0xff, 2, unsigned, false),
|
||||||
RL78REL (DIR8UW, 0, 8, 1, unsigned, false),
|
RL78REL (DIR8UW, 0, 8, 0xff, 1, unsigned, false),
|
||||||
RL78REL (DIR32_REV, 1, 16, 0, dont, false),
|
RL78REL (DIR32_REV, 2, 32, 0xffffffff, 0, dont, false),
|
||||||
RL78REL (DIR16_REV, 1, 16, 0, dont, false),
|
RL78REL (DIR16_REV, 1, 16, 0xffff, 0, bitfield, false),
|
||||||
RL78REL (DIR3U_PCREL, 0, 3, 0, dont, true),
|
RL78REL (DIR3U_PCREL, 0, 3, 0x7, 0, unsigned, true),
|
||||||
|
|
||||||
EMPTY_HOWTO (0x13),
|
EMPTY_HOWTO (0x13),
|
||||||
EMPTY_HOWTO (0x14),
|
EMPTY_HOWTO (0x14),
|
||||||
|
@ -92,10 +91,11 @@ static reloc_howto_type rl78_elf_howto_table [] =
|
||||||
EMPTY_HOWTO (0x2a),
|
EMPTY_HOWTO (0x2a),
|
||||||
EMPTY_HOWTO (0x2b),
|
EMPTY_HOWTO (0x2b),
|
||||||
EMPTY_HOWTO (0x2c),
|
EMPTY_HOWTO (0x2c),
|
||||||
RL78REL (RH_RELAX, 0, 0, 0, dont, false),
|
|
||||||
|
|
||||||
EMPTY_HOWTO (0x2e),
|
RL78REL (RH_RELAX, 3, 0, 0, 0, dont, false),
|
||||||
RL78REL (RH_SADDR, 0, 0, 0, dont, false),
|
RL78REL (RH_SFR, 0, 8, 0xff, 0, unsigned, false),
|
||||||
|
RL78REL (RH_SADDR, 0, 8, 0xff, 0, unsigned, false),
|
||||||
|
|
||||||
EMPTY_HOWTO (0x30),
|
EMPTY_HOWTO (0x30),
|
||||||
EMPTY_HOWTO (0x31),
|
EMPTY_HOWTO (0x31),
|
||||||
EMPTY_HOWTO (0x32),
|
EMPTY_HOWTO (0x32),
|
||||||
|
@ -114,23 +114,23 @@ static reloc_howto_type rl78_elf_howto_table [] =
|
||||||
EMPTY_HOWTO (0x3f),
|
EMPTY_HOWTO (0x3f),
|
||||||
EMPTY_HOWTO (0x40),
|
EMPTY_HOWTO (0x40),
|
||||||
|
|
||||||
RL78_OP_REL (ABS32, 2, 32, 0, dont, false),
|
RL78_OP_REL (ABS32, 2, 32, 0xffffffff, 0, dont, false),
|
||||||
RL78_OP_REL (ABS24S, 2, 24, 0, signed, false),
|
RL78_OP_REL (ABS24S, 2, 24, 0xffffff, 0, signed, false),
|
||||||
RL78_OP_REL (ABS16, 1, 16, 0, dont, false),
|
RL78_OP_REL (ABS16, 1, 16, 0xffff, 0, bitfield, false),
|
||||||
RL78_OP_REL (ABS16U, 1, 16, 0, unsigned, false),
|
RL78_OP_REL (ABS16U, 1, 16, 0xffff, 0, unsigned, false),
|
||||||
RL78_OP_REL (ABS16S, 1, 16, 0, signed, false),
|
RL78_OP_REL (ABS16S, 1, 16, 0xffff, 0, signed, false),
|
||||||
RL78_OP_REL (ABS8, 0, 8, 0, dont, false),
|
RL78_OP_REL (ABS8, 0, 8, 0xff, 0, bitfield, false),
|
||||||
RL78_OP_REL (ABS8U, 0, 8, 0, unsigned, false),
|
RL78_OP_REL (ABS8U, 0, 8, 0xff, 0, unsigned, false),
|
||||||
RL78_OP_REL (ABS8S, 0, 8, 0, signed, false),
|
RL78_OP_REL (ABS8S, 0, 8, 0xff, 0, signed, false),
|
||||||
RL78_OP_REL (ABS24S_PCREL, 2, 24, 0, signed, true),
|
RL78_OP_REL (ABS24S_PCREL, 2, 24, 0xffffff, 0, signed, true),
|
||||||
RL78_OP_REL (ABS16S_PCREL, 1, 16, 0, signed, true),
|
RL78_OP_REL (ABS16S_PCREL, 1, 16, 0xffff, 0, signed, true),
|
||||||
RL78_OP_REL (ABS8S_PCREL, 0, 8, 0, signed, true),
|
RL78_OP_REL (ABS8S_PCREL, 0, 8, 0xff, 0, signed, true),
|
||||||
RL78_OP_REL (ABS16UL, 1, 16, 0, unsigned, false),
|
RL78_OP_REL (ABS16UL, 1, 16, 0xffff, 0, unsigned, false),
|
||||||
RL78_OP_REL (ABS16UW, 1, 16, 0, unsigned, false),
|
RL78_OP_REL (ABS16UW, 1, 16, 0xffff, 0, unsigned, false),
|
||||||
RL78_OP_REL (ABS8UL, 0, 8, 0, unsigned, false),
|
RL78_OP_REL (ABS8UL, 0, 8, 0xff, 0, unsigned, false),
|
||||||
RL78_OP_REL (ABS8UW, 0, 8, 0, unsigned, false),
|
RL78_OP_REL (ABS8UW, 0, 8, 0xff, 0, unsigned, false),
|
||||||
RL78_OP_REL (ABS32_REV, 2, 32, 0, dont, false),
|
RL78_OP_REL (ABS32_REV, 2, 32, 0xffffffff, 0, dont, false),
|
||||||
RL78_OP_REL (ABS16_REV, 1, 16, 0, dont, false),
|
RL78_OP_REL (ABS16_REV, 1, 16, 0xffff, 0, bitfield, false),
|
||||||
|
|
||||||
#define STACK_REL_P(x) ((x) <= R_RL78_ABS16_REV && (x) >= R_RL78_ABS32)
|
#define STACK_REL_P(x) ((x) <= R_RL78_ABS16_REV && (x) >= R_RL78_ABS32)
|
||||||
|
|
||||||
|
@ -182,29 +182,29 @@ static reloc_howto_type rl78_elf_howto_table [] =
|
||||||
EMPTY_HOWTO (0x7e),
|
EMPTY_HOWTO (0x7e),
|
||||||
EMPTY_HOWTO (0x7f),
|
EMPTY_HOWTO (0x7f),
|
||||||
|
|
||||||
RL78_OP_REL (SYM, 2, 32, 0, dont, false),
|
RL78_OP_REL (SYM, 3, 0, 0, 0, dont, false),
|
||||||
RL78_OP_REL (OPneg, 2, 32, 0, dont, false),
|
RL78_OP_REL (OPneg, 3, 0, 0, 0, dont, false),
|
||||||
RL78_OP_REL (OPadd, 2, 32, 0, dont, false),
|
RL78_OP_REL (OPadd, 3, 0, 0, 0, dont, false),
|
||||||
RL78_OP_REL (OPsub, 2, 32, 0, dont, false),
|
RL78_OP_REL (OPsub, 3, 0, 0, 0, dont, false),
|
||||||
RL78_OP_REL (OPmul, 2, 32, 0, dont, false),
|
RL78_OP_REL (OPmul, 3, 0, 0, 0, dont, false),
|
||||||
RL78_OP_REL (OPdiv, 2, 32, 0, dont, false),
|
RL78_OP_REL (OPdiv, 3, 0, 0, 0, dont, false),
|
||||||
RL78_OP_REL (OPshla, 2, 32, 0, dont, false),
|
RL78_OP_REL (OPshla, 3, 0, 0, 0, dont, false),
|
||||||
RL78_OP_REL (OPshra, 2, 32, 0, dont, false),
|
RL78_OP_REL (OPshra, 3, 0, 0, 0, dont, false),
|
||||||
RL78_OP_REL (OPsctsize, 2, 32, 0, dont, false),
|
RL78_OP_REL (OPsctsize, 3, 0, 0, 0, dont, false),
|
||||||
EMPTY_HOWTO (0x89),
|
EMPTY_HOWTO (0x89),
|
||||||
EMPTY_HOWTO (0x8a),
|
EMPTY_HOWTO (0x8a),
|
||||||
EMPTY_HOWTO (0x8b),
|
EMPTY_HOWTO (0x8b),
|
||||||
EMPTY_HOWTO (0x8c),
|
EMPTY_HOWTO (0x8c),
|
||||||
RL78_OP_REL (OPscttop, 2, 32, 0, dont, false),
|
RL78_OP_REL (OPscttop, 3, 0, 0, 0, dont, false),
|
||||||
EMPTY_HOWTO (0x8e),
|
EMPTY_HOWTO (0x8e),
|
||||||
EMPTY_HOWTO (0x8f),
|
EMPTY_HOWTO (0x8f),
|
||||||
RL78_OP_REL (OPand, 2, 32, 0, dont, false),
|
RL78_OP_REL (OPand, 3, 0, 0, 0, dont, false),
|
||||||
RL78_OP_REL (OPor, 2, 32, 0, dont, false),
|
RL78_OP_REL (OPor, 3, 0, 0, 0, dont, false),
|
||||||
RL78_OP_REL (OPxor, 2, 32, 0, dont, false),
|
RL78_OP_REL (OPxor, 3, 0, 0, 0, dont, false),
|
||||||
RL78_OP_REL (OPnot, 2, 32, 0, dont, false),
|
RL78_OP_REL (OPnot, 3, 0, 0, 0, dont, false),
|
||||||
RL78_OP_REL (OPmod, 2, 32, 0, dont, false),
|
RL78_OP_REL (OPmod, 3, 0, 0, 0, dont, false),
|
||||||
RL78_OP_REL (OPromtop, 2, 32, 0, dont, false),
|
RL78_OP_REL (OPromtop, 3, 0, 0, 0, dont, false),
|
||||||
RL78_OP_REL (OPramtop, 2, 32, 0, dont, false)
|
RL78_OP_REL (OPramtop, 3, 0, 0, 0, dont, false)
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Map BFD reloc types to RL78 ELF reloc types. */
|
/* Map BFD reloc types to RL78 ELF reloc types. */
|
||||||
|
@ -559,7 +559,36 @@ rl78_compute_complex_reloc (unsigned long r_type,
|
||||||
return relocation;
|
return relocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define OP(i) (contents[reloc->address + (i)])
|
/* Check whether RELOCATION overflows a relocation field described by
|
||||||
|
HOWTO. */
|
||||||
|
|
||||||
|
static bfd_reloc_status_type
|
||||||
|
check_overflow (reloc_howto_type *howto, bfd_vma relocation)
|
||||||
|
{
|
||||||
|
switch (howto->complain_on_overflow)
|
||||||
|
{
|
||||||
|
case complain_overflow_dont:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case complain_overflow_bitfield:
|
||||||
|
if ((bfd_signed_vma) relocation < -(1LL << (howto->bitsize - 1))
|
||||||
|
|| (bfd_signed_vma) relocation >= 1LL << howto->bitsize)
|
||||||
|
return bfd_reloc_overflow;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case complain_overflow_signed:
|
||||||
|
if ((bfd_signed_vma) relocation < -(1LL << (howto->bitsize - 1))
|
||||||
|
|| (bfd_signed_vma) relocation >= 1LL << (howto->bitsize - 1))
|
||||||
|
return bfd_reloc_overflow;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case complain_overflow_unsigned:
|
||||||
|
if (relocation >= 1ULL << howto->bitsize)
|
||||||
|
return bfd_reloc_overflow;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return bfd_reloc_ok;
|
||||||
|
}
|
||||||
|
|
||||||
static bfd_reloc_status_type
|
static bfd_reloc_status_type
|
||||||
rl78_special_reloc (bfd * input_bfd,
|
rl78_special_reloc (bfd * input_bfd,
|
||||||
|
@ -600,67 +629,42 @@ rl78_special_reloc (bfd * input_bfd,
|
||||||
relocation = rl78_compute_complex_reloc (r_type, relocation, input_section,
|
relocation = rl78_compute_complex_reloc (r_type, relocation, input_section,
|
||||||
&r, error_message);
|
&r, error_message);
|
||||||
|
|
||||||
/* If the relocation alters the contents of the section then apply it now.
|
if (STACK_REL_P (r_type))
|
||||||
Note - since this function is called from
|
|
||||||
bfd_generic_get_relocated_section_contents via bfd_perform_relocation,
|
|
||||||
and not from the linker, we do not perform any range checking. The
|
|
||||||
clients who are calling us are only interested in some relocated section
|
|
||||||
contents, and not any linkage problems that might occur later. */
|
|
||||||
switch (r_type)
|
|
||||||
{
|
{
|
||||||
case R_RL78_ABS32:
|
bfd_size_type limit;
|
||||||
OP (0) = relocation;
|
unsigned int nbytes;
|
||||||
OP (1) = relocation >> 8;
|
|
||||||
OP (2) = relocation >> 16;
|
|
||||||
OP (3) = relocation >> 24;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_ABS32_REV:
|
if (r == bfd_reloc_ok)
|
||||||
OP (3) = relocation;
|
r = check_overflow (reloc->howto, relocation);
|
||||||
OP (2) = relocation >> 8;
|
|
||||||
OP (1) = relocation >> 16;
|
|
||||||
OP (0) = relocation >> 24;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_ABS24S_PCREL:
|
if (r_type == R_RL78_ABS16_REV)
|
||||||
case R_RL78_ABS24S:
|
relocation = ((relocation & 0xff) << 8) | ((relocation >> 8) & 0xff);
|
||||||
OP (0) = relocation;
|
else if (r_type == R_RL78_ABS32_REV)
|
||||||
OP (1) = relocation >> 8;
|
relocation = (((relocation & 0xff) << 24)
|
||||||
OP (2) = relocation >> 16;
|
| ((relocation & 0xff00) << 8)
|
||||||
break;
|
| ((relocation >> 8) & 0xff00)
|
||||||
|
| ((relocation >> 24) & 0xff));
|
||||||
|
|
||||||
case R_RL78_ABS16_REV:
|
limit = bfd_get_section_limit_octets (input_bfd, input_section);
|
||||||
OP (1) = relocation;
|
nbytes = reloc->howto->bitsize / 8;
|
||||||
OP (0) = relocation >> 8;
|
if (reloc->address < limit
|
||||||
break;
|
&& nbytes <= limit - reloc->address)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
case R_RL78_ABS16S_PCREL:
|
for (i = 0; i < nbytes; i++)
|
||||||
case R_RL78_ABS16:
|
{
|
||||||
case R_RL78_ABS16S:
|
contents[reloc->address + i] = relocation;
|
||||||
case R_RL78_ABS16U:
|
relocation >>= 8;
|
||||||
case R_RL78_ABS16UL:
|
}
|
||||||
case R_RL78_ABS16UW:
|
}
|
||||||
OP (0) = relocation;
|
else
|
||||||
OP (1) = relocation >> 8;
|
r = bfd_reloc_outofrange;
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_ABS8S_PCREL:
|
|
||||||
case R_RL78_ABS8:
|
|
||||||
case R_RL78_ABS8U:
|
|
||||||
case R_RL78_ABS8UL:
|
|
||||||
case R_RL78_ABS8UW:
|
|
||||||
case R_RL78_ABS8S:
|
|
||||||
OP (0) = relocation;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef OP
|
|
||||||
#define OP(i) (contents[rel->r_offset + (i)])
|
#define OP(i) (contents[rel->r_offset + (i)])
|
||||||
|
|
||||||
/* Relocate an RL78 ELF section.
|
/* Relocate an RL78 ELF section.
|
||||||
|
@ -848,10 +852,12 @@ rl78_elf_relocate_section
|
||||||
}
|
}
|
||||||
|
|
||||||
r = bfd_reloc_ok;
|
r = bfd_reloc_ok;
|
||||||
|
if (howto->bitsize != 0
|
||||||
#define RANGE(a,b) if (a > (long) relocation || (long) relocation > b) r = bfd_reloc_overflow
|
&& (rel->r_offset >= input_section->size
|
||||||
|
|| ((howto->bitsize + 7u) / 8
|
||||||
/* Opcode relocs are always big endian. Data relocs are bi-endian. */
|
> input_section->size - rel->r_offset)))
|
||||||
|
r = bfd_reloc_outofrange;
|
||||||
|
else
|
||||||
switch (r_type)
|
switch (r_type)
|
||||||
{
|
{
|
||||||
case R_RL78_NONE:
|
case R_RL78_NONE:
|
||||||
|
@ -861,22 +867,18 @@ rl78_elf_relocate_section
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_DIR8S_PCREL:
|
case R_RL78_DIR8S_PCREL:
|
||||||
RANGE (-128, 127);
|
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_DIR8S:
|
case R_RL78_DIR8S:
|
||||||
RANGE (-128, 255);
|
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_DIR8U:
|
case R_RL78_DIR8U:
|
||||||
RANGE (0, 255);
|
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_DIR16S_PCREL:
|
case R_RL78_DIR16S_PCREL:
|
||||||
RANGE (-32768, 32767);
|
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
OP (1) = relocation >> 8;
|
OP (1) = relocation >> 8;
|
||||||
break;
|
break;
|
||||||
|
@ -884,44 +886,40 @@ rl78_elf_relocate_section
|
||||||
case R_RL78_DIR16S:
|
case R_RL78_DIR16S:
|
||||||
if ((relocation & 0xf0000) == 0xf0000)
|
if ((relocation & 0xf0000) == 0xf0000)
|
||||||
relocation &= 0xffff;
|
relocation &= 0xffff;
|
||||||
RANGE (-32768, 65535);
|
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
OP (1) = relocation >> 8;
|
OP (1) = relocation >> 8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_DIR16U:
|
case R_RL78_DIR16U:
|
||||||
RANGE (0, 65536);
|
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
OP (1) = relocation >> 8;
|
OP (1) = relocation >> 8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_DIR16:
|
case R_RL78_DIR16:
|
||||||
RANGE (-32768, 65536);
|
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
OP (1) = relocation >> 8;
|
OP (1) = relocation >> 8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_DIR16_REV:
|
case R_RL78_DIR16_REV:
|
||||||
RANGE (-32768, 65536);
|
|
||||||
OP (1) = relocation;
|
OP (1) = relocation;
|
||||||
OP (0) = relocation >> 8;
|
OP (0) = relocation >> 8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_DIR3U_PCREL:
|
case R_RL78_DIR3U_PCREL:
|
||||||
RANGE (3, 10);
|
|
||||||
OP (0) &= 0xf8;
|
OP (0) &= 0xf8;
|
||||||
OP (0) |= relocation & 0x07;
|
OP (0) |= relocation & 0x07;
|
||||||
|
/* Map [3, 10] to [0, 7]. The code below using howto
|
||||||
|
bitsize will check for unsigned overflow. */
|
||||||
|
relocation -= 3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_DIR24S_PCREL:
|
case R_RL78_DIR24S_PCREL:
|
||||||
RANGE (-0x800000, 0x7fffff);
|
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
OP (1) = relocation >> 8;
|
OP (1) = relocation >> 8;
|
||||||
OP (2) = relocation >> 16;
|
OP (2) = relocation >> 16;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_DIR24S:
|
case R_RL78_DIR24S:
|
||||||
RANGE (-0x800000, 0x7fffff);
|
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
OP (1) = relocation >> 8;
|
OP (1) = relocation >> 8;
|
||||||
OP (2) = relocation >> 16;
|
OP (2) = relocation >> 16;
|
||||||
|
@ -942,13 +940,13 @@ rl78_elf_relocate_section
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_RH_SFR:
|
case R_RL78_RH_SFR:
|
||||||
RANGE (0xfff00, 0xfffff);
|
relocation -= 0xfff00;
|
||||||
OP (0) = relocation & 0xff;
|
OP (0) = relocation;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_RH_SADDR:
|
case R_RL78_RH_SADDR:
|
||||||
RANGE (0xffe20, 0xfff1f);
|
relocation -= 0xffe20;
|
||||||
OP (0) = (relocation - 0x20) & 0xff;
|
OP (0) = relocation;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Complex reloc handling: */
|
/* Complex reloc handling: */
|
||||||
|
@ -1004,27 +1002,23 @@ rl78_elf_relocate_section
|
||||||
|
|
||||||
case R_RL78_ABS24S_PCREL:
|
case R_RL78_ABS24S_PCREL:
|
||||||
case R_RL78_ABS24S:
|
case R_RL78_ABS24S:
|
||||||
RANGE (-0x800000, 0x7fffff);
|
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
OP (1) = relocation >> 8;
|
OP (1) = relocation >> 8;
|
||||||
OP (2) = relocation >> 16;
|
OP (2) = relocation >> 16;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_ABS16:
|
case R_RL78_ABS16:
|
||||||
RANGE (-32768, 65535);
|
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
OP (1) = relocation >> 8;
|
OP (1) = relocation >> 8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_ABS16_REV:
|
case R_RL78_ABS16_REV:
|
||||||
RANGE (-32768, 65535);
|
|
||||||
OP (1) = relocation;
|
OP (1) = relocation;
|
||||||
OP (0) = relocation >> 8;
|
OP (0) = relocation >> 8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_ABS16S_PCREL:
|
case R_RL78_ABS16S_PCREL:
|
||||||
case R_RL78_ABS16S:
|
case R_RL78_ABS16S:
|
||||||
RANGE (-32768, 32767);
|
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
OP (1) = relocation >> 8;
|
OP (1) = relocation >> 8;
|
||||||
break;
|
break;
|
||||||
|
@ -1032,26 +1026,22 @@ rl78_elf_relocate_section
|
||||||
case R_RL78_ABS16U:
|
case R_RL78_ABS16U:
|
||||||
case R_RL78_ABS16UL:
|
case R_RL78_ABS16UL:
|
||||||
case R_RL78_ABS16UW:
|
case R_RL78_ABS16UW:
|
||||||
RANGE (0, 65536);
|
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
OP (1) = relocation >> 8;
|
OP (1) = relocation >> 8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_ABS8:
|
case R_RL78_ABS8:
|
||||||
RANGE (-128, 255);
|
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_ABS8U:
|
case R_RL78_ABS8U:
|
||||||
case R_RL78_ABS8UL:
|
case R_RL78_ABS8UL:
|
||||||
case R_RL78_ABS8UW:
|
case R_RL78_ABS8UW:
|
||||||
RANGE (0, 255);
|
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_ABS8S_PCREL:
|
case R_RL78_ABS8S_PCREL:
|
||||||
case R_RL78_ABS8S:
|
case R_RL78_ABS8S:
|
||||||
RANGE (-128, 127);
|
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1083,13 +1073,15 @@ rl78_elf_relocate_section
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_OPromtop:
|
case R_RL78_OPromtop:
|
||||||
relocation = get_romstart (info, input_bfd, input_section, rel->r_offset);
|
relocation = get_romstart (info, input_bfd, input_section,
|
||||||
|
rel->r_offset);
|
||||||
(void) rl78_compute_complex_reloc (r_type, relocation, input_section,
|
(void) rl78_compute_complex_reloc (r_type, relocation, input_section,
|
||||||
&r, &error_message);
|
&r, &error_message);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_OPramtop:
|
case R_RL78_OPramtop:
|
||||||
relocation = get_ramstart (info, input_bfd, input_section, rel->r_offset);
|
relocation = get_ramstart (info, input_bfd, input_section,
|
||||||
|
rel->r_offset);
|
||||||
(void) rl78_compute_complex_reloc (r_type, relocation, input_section,
|
(void) rl78_compute_complex_reloc (r_type, relocation, input_section,
|
||||||
&r, &error_message);
|
&r, &error_message);
|
||||||
break;
|
break;
|
||||||
|
@ -1099,6 +1091,9 @@ rl78_elf_relocate_section
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (r == bfd_reloc_ok)
|
||||||
|
r = check_overflow (howto, relocation);
|
||||||
|
|
||||||
if (r != bfd_reloc_ok)
|
if (r != bfd_reloc_ok)
|
||||||
{
|
{
|
||||||
switch (r)
|
switch (r)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue