Adds support to the RL78 port for linker relaxation affecting .debug sections.
gas * config/tc-rl78.h (TC_LINKRELAX_FIXUP): Define. (TC_FORCE_RELOCATION_SUB_SAME): Define. (DWARF2_USE_FIXED_ADVANCE_PC): Define. * gas/lns/lns.exp: Add RL78 to list of targets using DW_LNS_fixed_advance_pc. bfd * elf32-rl78.c (RL78_OP_REL): New macro. (rl78_elf_howto_table): Use it for complex relocs. (get_symbol_value): Handle the cases when the info or status arguments are NULL. (get_romstart): Cache the status returned by get_symbol_value. (get_ramstart): Likewise. (RL78_STACK_PUSH): Generate an error message if the stack overflows. (RL78_STACK_POP): Likewise for underflows. (rl78_compute_complex_reloc): New function. Contains the basic processing code for all RL78 complex relocs. (rl78_special_reloc): New function. Provides special reloc handling for complex relocs. (rl78_elf_relocate_section): Use rl78_compute_complex_reloc. (rl78_offset_for_reloc): Likewise. binutils* readelf.c (target_specific_reloc_handling): Add code to handle RL78 complex relocs.
This commit is contained in:
parent
9e811bc379
commit
6ff71e7681
9 changed files with 582 additions and 427 deletions
|
@ -1,3 +1,21 @@
|
||||||
|
2015-04-14 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
* elf32-rl78.c (RL78_OP_REL): New macro.
|
||||||
|
(rl78_elf_howto_table): Use it for complex relocs.
|
||||||
|
(get_symbol_value): Handle the cases when the info or status
|
||||||
|
arguments are NULL.
|
||||||
|
(get_romstart): Cache the status returned by get_symbol_value.
|
||||||
|
(get_ramstart): Likewise.
|
||||||
|
(RL78_STACK_PUSH): Generate an error message if the stack
|
||||||
|
overflows.
|
||||||
|
(RL78_STACK_POP): Likewise for underflows.
|
||||||
|
(rl78_compute_complex_reloc): New function. Contains the basic
|
||||||
|
processing code for all RL78 complex relocs.
|
||||||
|
(rl78_special_reloc): New function. Provides special reloc
|
||||||
|
handling for complex relocs.
|
||||||
|
(rl78_elf_relocate_section): Use rl78_compute_complex_reloc.
|
||||||
|
(rl78_offset_for_reloc): Likewise.
|
||||||
|
|
||||||
2015-04-14 H.J. Lu <hongjiu.lu@intel.com>
|
2015-04-14 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
PR ld/pr17709
|
PR ld/pr17709
|
||||||
|
|
753
bfd/elf32-rl78.c
753
bfd/elf32-rl78.c
|
@ -31,6 +31,14 @@
|
||||||
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, ~0, FALSE)
|
||||||
|
|
||||||
|
static bfd_reloc_status_type rl78_special_reloc (bfd *, arelent *, asymbol *, void *,
|
||||||
|
asection *, bfd *, char **);
|
||||||
|
|
||||||
|
/* FIXME: We could omit the SHIFT parameter, it is always zero. */
|
||||||
|
#define RL78_OP_REL(n,sz,bit,shift,complain,pcrel) \
|
||||||
|
HOWTO (R_RL78_##n, shift, sz, bit, pcrel, 0, complain_overflow_ ## complain, \
|
||||||
|
rl78_special_reloc, "R_RL78_" #n, FALSE, 0, ~0, 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
|
||||||
relocation numbers. */
|
relocation numbers. */
|
||||||
|
@ -106,23 +114,23 @@ static reloc_howto_type rl78_elf_howto_table [] =
|
||||||
EMPTY_HOWTO (0x3f),
|
EMPTY_HOWTO (0x3f),
|
||||||
EMPTY_HOWTO (0x40),
|
EMPTY_HOWTO (0x40),
|
||||||
|
|
||||||
RL78REL (ABS32, 2, 32, 0, dont, FALSE),
|
RL78_OP_REL (ABS32, 2, 32, 0, dont, FALSE),
|
||||||
RL78REL (ABS24S, 2, 24, 0, signed, FALSE),
|
RL78_OP_REL (ABS24S, 2, 24, 0, signed, FALSE),
|
||||||
RL78REL (ABS16, 1, 16, 0, dont, FALSE),
|
RL78_OP_REL (ABS16, 1, 16, 0, dont, FALSE),
|
||||||
RL78REL (ABS16U, 1, 16, 0, unsigned, FALSE),
|
RL78_OP_REL (ABS16U, 1, 16, 0, unsigned, FALSE),
|
||||||
RL78REL (ABS16S, 1, 16, 0, signed, FALSE),
|
RL78_OP_REL (ABS16S, 1, 16, 0, signed, FALSE),
|
||||||
RL78REL (ABS8, 0, 8, 0, dont, FALSE),
|
RL78_OP_REL (ABS8, 0, 8, 0, dont, FALSE),
|
||||||
RL78REL (ABS8U, 0, 8, 0, unsigned, FALSE),
|
RL78_OP_REL (ABS8U, 0, 8, 0, unsigned, FALSE),
|
||||||
RL78REL (ABS8S, 0, 8, 0, signed, FALSE),
|
RL78_OP_REL (ABS8S, 0, 8, 0, signed, FALSE),
|
||||||
RL78REL (ABS24S_PCREL, 2, 24, 0, signed, TRUE),
|
RL78_OP_REL (ABS24S_PCREL, 2, 24, 0, signed, TRUE),
|
||||||
RL78REL (ABS16S_PCREL, 1, 16, 0, signed, TRUE),
|
RL78_OP_REL (ABS16S_PCREL, 1, 16, 0, signed, TRUE),
|
||||||
RL78REL (ABS8S_PCREL, 0, 8, 0, signed, TRUE),
|
RL78_OP_REL (ABS8S_PCREL, 0, 8, 0, signed, TRUE),
|
||||||
RL78REL (ABS16UL, 1, 16, 0, unsigned, FALSE),
|
RL78_OP_REL (ABS16UL, 1, 16, 0, unsigned, FALSE),
|
||||||
RL78REL (ABS16UW, 1, 16, 0, unsigned, FALSE),
|
RL78_OP_REL (ABS16UW, 1, 16, 0, unsigned, FALSE),
|
||||||
RL78REL (ABS8UL, 0, 8, 0, unsigned, FALSE),
|
RL78_OP_REL (ABS8UL, 0, 8, 0, unsigned, FALSE),
|
||||||
RL78REL (ABS8UW, 0, 8, 0, unsigned, FALSE),
|
RL78_OP_REL (ABS8UW, 0, 8, 0, unsigned, FALSE),
|
||||||
RL78REL (ABS32_REV, 2, 32, 0, dont, FALSE),
|
RL78_OP_REL (ABS32_REV, 2, 32, 0, dont, FALSE),
|
||||||
RL78REL (ABS16_REV, 1, 16, 0, dont, FALSE),
|
RL78_OP_REL (ABS16_REV, 1, 16, 0, dont, 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)
|
||||||
|
|
||||||
|
@ -174,29 +182,29 @@ static reloc_howto_type rl78_elf_howto_table [] =
|
||||||
EMPTY_HOWTO (0x7e),
|
EMPTY_HOWTO (0x7e),
|
||||||
EMPTY_HOWTO (0x7f),
|
EMPTY_HOWTO (0x7f),
|
||||||
|
|
||||||
RL78REL (SYM, 2, 32, 0, dont, FALSE),
|
RL78_OP_REL (SYM, 2, 32, 0, dont, FALSE),
|
||||||
RL78REL (OPneg, 2, 32, 0, dont, FALSE),
|
RL78_OP_REL (OPneg, 2, 32, 0, dont, FALSE),
|
||||||
RL78REL (OPadd, 2, 32, 0, dont, FALSE),
|
RL78_OP_REL (OPadd, 2, 32, 0, dont, FALSE),
|
||||||
RL78REL (OPsub, 2, 32, 0, dont, FALSE),
|
RL78_OP_REL (OPsub, 2, 32, 0, dont, FALSE),
|
||||||
RL78REL (OPmul, 2, 32, 0, dont, FALSE),
|
RL78_OP_REL (OPmul, 2, 32, 0, dont, FALSE),
|
||||||
RL78REL (OPdiv, 2, 32, 0, dont, FALSE),
|
RL78_OP_REL (OPdiv, 2, 32, 0, dont, FALSE),
|
||||||
RL78REL (OPshla, 2, 32, 0, dont, FALSE),
|
RL78_OP_REL (OPshla, 2, 32, 0, dont, FALSE),
|
||||||
RL78REL (OPshra, 2, 32, 0, dont, FALSE),
|
RL78_OP_REL (OPshra, 2, 32, 0, dont, FALSE),
|
||||||
RL78REL (OPsctsize, 2, 32, 0, dont, FALSE),
|
RL78_OP_REL (OPsctsize, 2, 32, 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),
|
||||||
RL78REL (OPscttop, 2, 32, 0, dont, FALSE),
|
RL78_OP_REL (OPscttop, 2, 32, 0, dont, FALSE),
|
||||||
EMPTY_HOWTO (0x8e),
|
EMPTY_HOWTO (0x8e),
|
||||||
EMPTY_HOWTO (0x8f),
|
EMPTY_HOWTO (0x8f),
|
||||||
RL78REL (OPand, 2, 32, 0, dont, FALSE),
|
RL78_OP_REL (OPand, 2, 32, 0, dont, FALSE),
|
||||||
RL78REL (OPor, 2, 32, 0, dont, FALSE),
|
RL78_OP_REL (OPor, 2, 32, 0, dont, FALSE),
|
||||||
RL78REL (OPxor, 2, 32, 0, dont, FALSE),
|
RL78_OP_REL (OPxor, 2, 32, 0, dont, FALSE),
|
||||||
RL78REL (OPnot, 2, 32, 0, dont, FALSE),
|
RL78_OP_REL (OPnot, 2, 32, 0, dont, FALSE),
|
||||||
RL78REL (OPmod, 2, 32, 0, dont, FALSE),
|
RL78_OP_REL (OPmod, 2, 32, 0, dont, FALSE),
|
||||||
RL78REL (OPromtop, 2, 32, 0, dont, FALSE),
|
RL78_OP_REL (OPromtop, 2, 32, 0, dont, FALSE),
|
||||||
RL78REL (OPramtop, 2, 32, 0, dont, FALSE)
|
RL78_OP_REL (OPramtop, 2, 32, 0, dont, FALSE)
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Map BFD reloc types to RL78 ELF reloc types. */
|
/* Map BFD reloc types to RL78 ELF reloc types. */
|
||||||
|
@ -292,22 +300,29 @@ get_symbol_value (const char * name,
|
||||||
asection * input_section,
|
asection * input_section,
|
||||||
int offset)
|
int offset)
|
||||||
{
|
{
|
||||||
bfd_vma value = 0;
|
|
||||||
struct bfd_link_hash_entry * h;
|
struct bfd_link_hash_entry * h;
|
||||||
|
|
||||||
|
if (info == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
|
h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE);
|
||||||
|
|
||||||
if (h == NULL
|
if (h == NULL
|
||||||
|| (h->type != bfd_link_hash_defined
|
|| (h->type != bfd_link_hash_defined
|
||||||
&& h->type != bfd_link_hash_defweak))
|
&& h->type != bfd_link_hash_defweak))
|
||||||
* status = info->callbacks->undefined_symbol
|
{
|
||||||
|
bfd_reloc_status_type res;
|
||||||
|
|
||||||
|
res = info->callbacks->undefined_symbol
|
||||||
(info, name, input_bfd, input_section, offset, TRUE);
|
(info, name, input_bfd, input_section, offset, TRUE);
|
||||||
else
|
if (status)
|
||||||
value = (h->u.def.value
|
* status = res;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (h->u.def.value
|
||||||
+ h->u.def.section->output_section->vma
|
+ h->u.def.section->output_section->vma
|
||||||
+ h->u.def.section->output_offset);
|
+ h->u.def.section->output_offset);
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bfd_vma
|
static bfd_vma
|
||||||
|
@ -319,12 +334,15 @@ get_romstart (bfd_reloc_status_type * status,
|
||||||
{
|
{
|
||||||
static bfd_boolean cached = FALSE;
|
static bfd_boolean cached = FALSE;
|
||||||
static bfd_vma cached_value = 0;
|
static bfd_vma cached_value = 0;
|
||||||
|
static bfd_reloc_status_type cached_status;
|
||||||
|
|
||||||
if (!cached)
|
if (!cached)
|
||||||
{
|
{
|
||||||
cached_value = get_symbol_value ("_start", status, info, abfd, sec, offset);
|
cached_value = get_symbol_value ("_start", & cached_status, info, abfd, sec, offset);
|
||||||
cached = TRUE;
|
cached = TRUE;
|
||||||
}
|
}
|
||||||
|
if (status)
|
||||||
|
* status = cached_status;
|
||||||
return cached_value;
|
return cached_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,12 +355,15 @@ get_ramstart (bfd_reloc_status_type * status,
|
||||||
{
|
{
|
||||||
static bfd_boolean cached = FALSE;
|
static bfd_boolean cached = FALSE;
|
||||||
static bfd_vma cached_value = 0;
|
static bfd_vma cached_value = 0;
|
||||||
|
static bfd_reloc_status_type cached_status;
|
||||||
|
|
||||||
if (!cached)
|
if (!cached)
|
||||||
{
|
{
|
||||||
cached_value = get_symbol_value ("__datastart", status, info, abfd, sec, offset);
|
cached_value = get_symbol_value ("__datastart", & cached_status, info, abfd, sec, offset);
|
||||||
cached = TRUE;
|
cached = TRUE;
|
||||||
}
|
}
|
||||||
|
if (status)
|
||||||
|
* status = cached_status;
|
||||||
return cached_value;
|
return cached_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,7 +377,7 @@ static unsigned int rl78_stack_top;
|
||||||
if (rl78_stack_top < NUM_STACK_ENTRIES) \
|
if (rl78_stack_top < NUM_STACK_ENTRIES) \
|
||||||
rl78_stack [rl78_stack_top ++] = (val); \
|
rl78_stack [rl78_stack_top ++] = (val); \
|
||||||
else \
|
else \
|
||||||
r = bfd_reloc_dangerous; \
|
_bfd_error_handler (_("Internal Error: RL78 reloc stack overflow")); \
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
|
@ -364,12 +385,269 @@ static unsigned int rl78_stack_top;
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
if (rl78_stack_top > 0) \
|
if (rl78_stack_top > 0) \
|
||||||
(dest) = rl78_stack [-- rl78_stack_top]; \
|
(dest) = rl78_stack [-- rl78_stack_top];\
|
||||||
else \
|
else \
|
||||||
(dest) = 0, r = bfd_reloc_dangerous; \
|
{ \
|
||||||
|
_bfd_error_handler (_("Internal Error: RL78 reloc stack underflow")); \
|
||||||
|
(dest) = 0; \
|
||||||
|
} \
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
|
/* Special handling for RL78 complex relocs. Returns the
|
||||||
|
value of the reloc, or 0 for relocs which do not generate
|
||||||
|
a result. SYMVAL is the value of the symbol for relocs
|
||||||
|
which use a symbolic argument. */
|
||||||
|
|
||||||
|
static bfd_vma
|
||||||
|
rl78_compute_complex_reloc (unsigned long r_type,
|
||||||
|
bfd_vma symval,
|
||||||
|
asection * input_section)
|
||||||
|
{
|
||||||
|
int32_t tmp1, tmp2;
|
||||||
|
bfd_vma relocation;
|
||||||
|
|
||||||
|
switch (r_type)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case R_RL78_ABS24S_PCREL:
|
||||||
|
case R_RL78_ABS16S_PCREL:
|
||||||
|
case R_RL78_ABS8S_PCREL:
|
||||||
|
RL78_STACK_POP (relocation);
|
||||||
|
relocation -= input_section->output_section->vma + input_section->output_offset;
|
||||||
|
return relocation;
|
||||||
|
|
||||||
|
case R_RL78_ABS32:
|
||||||
|
case R_RL78_ABS32_REV:
|
||||||
|
case R_RL78_ABS16:
|
||||||
|
case R_RL78_ABS16_REV:
|
||||||
|
case R_RL78_ABS16S:
|
||||||
|
case R_RL78_ABS16U:
|
||||||
|
case R_RL78_ABS8:
|
||||||
|
case R_RL78_ABS8U:
|
||||||
|
case R_RL78_ABS8S:
|
||||||
|
RL78_STACK_POP (relocation);
|
||||||
|
return relocation;
|
||||||
|
|
||||||
|
case R_RL78_ABS16UL:
|
||||||
|
case R_RL78_ABS8UL:
|
||||||
|
RL78_STACK_POP (relocation);
|
||||||
|
return relocation >> 2;
|
||||||
|
|
||||||
|
case R_RL78_ABS16UW:
|
||||||
|
case R_RL78_ABS8UW:
|
||||||
|
RL78_STACK_POP (relocation);
|
||||||
|
return relocation >> 1;
|
||||||
|
|
||||||
|
/* The rest of the relocs compute values and then push them onto the stack. */
|
||||||
|
case R_RL78_OPramtop:
|
||||||
|
case R_RL78_OPromtop:
|
||||||
|
case R_RL78_SYM:
|
||||||
|
RL78_STACK_PUSH (symval);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case R_RL78_OPneg:
|
||||||
|
RL78_STACK_POP (tmp1);
|
||||||
|
tmp1 = - tmp1;
|
||||||
|
RL78_STACK_PUSH (tmp1);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case R_RL78_OPadd:
|
||||||
|
RL78_STACK_POP (tmp2);
|
||||||
|
RL78_STACK_POP (tmp1);
|
||||||
|
tmp1 += tmp2;
|
||||||
|
RL78_STACK_PUSH (tmp1);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case R_RL78_OPsub:
|
||||||
|
/* For the expression "A - B", the assembler pushes A,
|
||||||
|
then B, then OPSUB. So the first op we pop is B, not A. */
|
||||||
|
RL78_STACK_POP (tmp2); /* B */
|
||||||
|
RL78_STACK_POP (tmp1); /* A */
|
||||||
|
tmp1 -= tmp2; /* A - B */
|
||||||
|
RL78_STACK_PUSH (tmp1);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case R_RL78_OPmul:
|
||||||
|
RL78_STACK_POP (tmp2);
|
||||||
|
RL78_STACK_POP (tmp1);
|
||||||
|
tmp1 *= tmp2;
|
||||||
|
RL78_STACK_PUSH (tmp1);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case R_RL78_OPdiv:
|
||||||
|
RL78_STACK_POP (tmp2);
|
||||||
|
RL78_STACK_POP (tmp1);
|
||||||
|
tmp1 /= tmp2;
|
||||||
|
RL78_STACK_PUSH (tmp1);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case R_RL78_OPshla:
|
||||||
|
RL78_STACK_POP (tmp2);
|
||||||
|
RL78_STACK_POP (tmp1);
|
||||||
|
tmp1 <<= tmp2;
|
||||||
|
RL78_STACK_PUSH (tmp1);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case R_RL78_OPshra:
|
||||||
|
RL78_STACK_POP (tmp2);
|
||||||
|
RL78_STACK_POP (tmp1);
|
||||||
|
tmp1 >>= tmp2;
|
||||||
|
RL78_STACK_PUSH (tmp1);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case R_RL78_OPsctsize:
|
||||||
|
RL78_STACK_PUSH (input_section->size);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case R_RL78_OPscttop:
|
||||||
|
RL78_STACK_PUSH (input_section->output_section->vma);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case R_RL78_OPand:
|
||||||
|
RL78_STACK_POP (tmp2);
|
||||||
|
RL78_STACK_POP (tmp1);
|
||||||
|
tmp1 &= tmp2;
|
||||||
|
RL78_STACK_PUSH (tmp1);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case R_RL78_OPor:
|
||||||
|
RL78_STACK_POP (tmp2);
|
||||||
|
RL78_STACK_POP (tmp1);
|
||||||
|
tmp1 |= tmp2;
|
||||||
|
RL78_STACK_PUSH (tmp1);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case R_RL78_OPxor:
|
||||||
|
RL78_STACK_POP (tmp2);
|
||||||
|
RL78_STACK_POP (tmp1);
|
||||||
|
tmp1 ^= tmp2;
|
||||||
|
RL78_STACK_PUSH (tmp1);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case R_RL78_OPnot:
|
||||||
|
RL78_STACK_POP (tmp1);
|
||||||
|
tmp1 = ~ tmp1;
|
||||||
|
RL78_STACK_PUSH (tmp1);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case R_RL78_OPmod:
|
||||||
|
RL78_STACK_POP (tmp2);
|
||||||
|
RL78_STACK_POP (tmp1);
|
||||||
|
tmp1 %= tmp2;
|
||||||
|
RL78_STACK_PUSH (tmp1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef RL78_STACK_PUSH
|
||||||
|
#undef RL78_STACK_POP
|
||||||
|
|
||||||
|
#define OP(i) (contents[reloc->address + (i)])
|
||||||
|
|
||||||
|
static bfd_reloc_status_type
|
||||||
|
rl78_special_reloc (bfd * input_bfd,
|
||||||
|
arelent * reloc,
|
||||||
|
asymbol * symbol,
|
||||||
|
void * data,
|
||||||
|
asection * input_section,
|
||||||
|
bfd * output_bfd ATTRIBUTE_UNUSED,
|
||||||
|
char ** error_message ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
bfd_reloc_status_type r = bfd_reloc_ok;
|
||||||
|
bfd_vma relocation = 0;
|
||||||
|
unsigned long r_type = reloc->howto->type;
|
||||||
|
bfd_byte * contents = data;
|
||||||
|
|
||||||
|
/* If necessary, compute the symbolic value of the relocation. */
|
||||||
|
switch (r_type)
|
||||||
|
{
|
||||||
|
case R_RL78_SYM:
|
||||||
|
relocation = (symbol->value
|
||||||
|
+ symbol->section->output_section->vma
|
||||||
|
+ symbol->section->output_offset
|
||||||
|
+ reloc->addend);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case R_RL78_OPromtop:
|
||||||
|
relocation = get_romstart (&r, NULL, input_bfd, input_section,
|
||||||
|
reloc->address);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case R_RL78_OPramtop:
|
||||||
|
relocation = get_ramstart (&r, NULL, input_bfd, input_section,
|
||||||
|
reloc->address);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the value of the relocation. */
|
||||||
|
relocation = rl78_compute_complex_reloc (r_type, relocation, input_section);
|
||||||
|
|
||||||
|
/* If the relocation alters the contents of the section then apply it now.
|
||||||
|
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:
|
||||||
|
OP (0) = relocation;
|
||||||
|
OP (1) = relocation >> 8;
|
||||||
|
OP (2) = relocation >> 16;
|
||||||
|
OP (3) = relocation >> 24;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case R_RL78_ABS32_REV:
|
||||||
|
OP (3) = relocation;
|
||||||
|
OP (2) = relocation >> 8;
|
||||||
|
OP (1) = relocation >> 16;
|
||||||
|
OP (0) = relocation >> 24;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case R_RL78_ABS24S_PCREL:
|
||||||
|
case R_RL78_ABS24S:
|
||||||
|
OP (0) = relocation;
|
||||||
|
OP (1) = relocation >> 8;
|
||||||
|
OP (2) = relocation >> 16;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case R_RL78_ABS16_REV:
|
||||||
|
OP (1) = relocation;
|
||||||
|
OP (0) = relocation >> 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case R_RL78_ABS16S_PCREL:
|
||||||
|
case R_RL78_ABS16:
|
||||||
|
case R_RL78_ABS16S:
|
||||||
|
case R_RL78_ABS16U:
|
||||||
|
case R_RL78_ABS16UL:
|
||||||
|
case R_RL78_ABS16UW:
|
||||||
|
OP (0) = relocation;
|
||||||
|
OP (1) = relocation >> 8;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef OP
|
||||||
|
#define OP(i) (contents[rel->r_offset + (i)])
|
||||||
|
|
||||||
/* Relocate an RL78 ELF section.
|
/* Relocate an RL78 ELF section.
|
||||||
There is some attempt to make this function usable for many architectures,
|
There is some attempt to make this function usable for many architectures,
|
||||||
both USE_REL and USE_RELA ['twould be nice if such a critter existed],
|
both USE_REL and USE_RELA ['twould be nice if such a critter existed],
|
||||||
|
@ -475,7 +753,7 @@ rl78_elf_relocate_section
|
||||||
name = h->root.root.string;
|
name = h->root.root.string;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sec != NULL && discarded_section (sec))
|
if (sec != NULL && discarded_section (sec)
|
||||||
RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
|
RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
|
||||||
rel, 1, relend, howto, 0, contents);
|
rel, 1, relend, howto, 0, contents);
|
||||||
|
|
||||||
|
@ -559,8 +837,6 @@ rl78_elf_relocate_section
|
||||||
r = bfd_reloc_ok;
|
r = bfd_reloc_ok;
|
||||||
|
|
||||||
#define RANGE(a,b) if (a > (long) relocation || (long) relocation > b) r = bfd_reloc_overflow
|
#define RANGE(a,b) if (a > (long) relocation || (long) relocation > b) r = bfd_reloc_overflow
|
||||||
#define ALIGN(m) if (relocation & m) r = bfd_reloc_other;
|
|
||||||
#define OP(i) (contents[rel->r_offset + (i)])
|
|
||||||
|
|
||||||
/* Opcode relocs are always big endian. Data relocs are bi-endian. */
|
/* Opcode relocs are always big endian. Data relocs are bi-endian. */
|
||||||
switch (r_type)
|
switch (r_type)
|
||||||
|
@ -663,9 +939,42 @@ rl78_elf_relocate_section
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Complex reloc handling: */
|
/* Complex reloc handling: */
|
||||||
|
|
||||||
case R_RL78_ABS32:
|
case R_RL78_ABS32:
|
||||||
RL78_STACK_POP (relocation);
|
case R_RL78_ABS32_REV:
|
||||||
|
case R_RL78_ABS24S_PCREL:
|
||||||
|
case R_RL78_ABS24S:
|
||||||
|
case R_RL78_ABS16:
|
||||||
|
case R_RL78_ABS16_REV:
|
||||||
|
case R_RL78_ABS16S_PCREL:
|
||||||
|
case R_RL78_ABS16S:
|
||||||
|
case R_RL78_ABS16U:
|
||||||
|
case R_RL78_ABS16UL:
|
||||||
|
case R_RL78_ABS16UW:
|
||||||
|
case R_RL78_ABS8:
|
||||||
|
case R_RL78_ABS8U:
|
||||||
|
case R_RL78_ABS8UL:
|
||||||
|
case R_RL78_ABS8UW:
|
||||||
|
case R_RL78_ABS8S_PCREL:
|
||||||
|
case R_RL78_ABS8S:
|
||||||
|
case R_RL78_OPneg:
|
||||||
|
case R_RL78_OPadd:
|
||||||
|
case R_RL78_OPsub:
|
||||||
|
case R_RL78_OPmul:
|
||||||
|
case R_RL78_OPdiv:
|
||||||
|
case R_RL78_OPshla:
|
||||||
|
case R_RL78_OPshra:
|
||||||
|
case R_RL78_OPsctsize:
|
||||||
|
case R_RL78_OPscttop:
|
||||||
|
case R_RL78_OPand:
|
||||||
|
case R_RL78_OPor:
|
||||||
|
case R_RL78_OPxor:
|
||||||
|
case R_RL78_OPnot:
|
||||||
|
case R_RL78_OPmod:
|
||||||
|
relocation = rl78_compute_complex_reloc (r_type, 0, input_section);
|
||||||
|
|
||||||
|
switch (r_type)
|
||||||
|
{
|
||||||
|
case R_RL78_ABS32:
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
OP (1) = relocation >> 8;
|
OP (1) = relocation >> 8;
|
||||||
OP (2) = relocation >> 16;
|
OP (2) = relocation >> 16;
|
||||||
|
@ -673,7 +982,6 @@ rl78_elf_relocate_section
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_ABS32_REV:
|
case R_RL78_ABS32_REV:
|
||||||
RL78_STACK_POP (relocation);
|
|
||||||
OP (3) = relocation;
|
OP (3) = relocation;
|
||||||
OP (2) = relocation >> 8;
|
OP (2) = relocation >> 8;
|
||||||
OP (1) = relocation >> 16;
|
OP (1) = relocation >> 16;
|
||||||
|
@ -682,7 +990,6 @@ rl78_elf_relocate_section
|
||||||
|
|
||||||
case R_RL78_ABS24S_PCREL:
|
case R_RL78_ABS24S_PCREL:
|
||||||
case R_RL78_ABS24S:
|
case R_RL78_ABS24S:
|
||||||
RL78_STACK_POP (relocation);
|
|
||||||
RANGE (-0x800000, 0x7fffff);
|
RANGE (-0x800000, 0x7fffff);
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
OP (1) = relocation >> 8;
|
OP (1) = relocation >> 8;
|
||||||
|
@ -690,14 +997,12 @@ rl78_elf_relocate_section
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_ABS16:
|
case R_RL78_ABS16:
|
||||||
RL78_STACK_POP (relocation);
|
|
||||||
RANGE (-32768, 65535);
|
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:
|
||||||
RL78_STACK_POP (relocation);
|
|
||||||
RANGE (-32768, 65535);
|
RANGE (-32768, 65535);
|
||||||
OP (1) = relocation;
|
OP (1) = relocation;
|
||||||
OP (0) = relocation >> 8;
|
OP (0) = relocation >> 8;
|
||||||
|
@ -705,237 +1010,70 @@ rl78_elf_relocate_section
|
||||||
|
|
||||||
case R_RL78_ABS16S_PCREL:
|
case R_RL78_ABS16S_PCREL:
|
||||||
case R_RL78_ABS16S:
|
case R_RL78_ABS16S:
|
||||||
RL78_STACK_POP (relocation);
|
|
||||||
RANGE (-32768, 32767);
|
RANGE (-32768, 32767);
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
OP (1) = relocation >> 8;
|
OP (1) = relocation >> 8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_ABS16U:
|
case R_RL78_ABS16U:
|
||||||
RL78_STACK_POP (relocation);
|
|
||||||
RANGE (0, 65536);
|
|
||||||
OP (0) = relocation;
|
|
||||||
OP (1) = relocation >> 8;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_ABS16UL:
|
case R_RL78_ABS16UL:
|
||||||
RL78_STACK_POP (relocation);
|
|
||||||
relocation >>= 2;
|
|
||||||
RANGE (0, 65536);
|
|
||||||
OP (0) = relocation;
|
|
||||||
OP (1) = relocation >> 8;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_ABS16UW:
|
case R_RL78_ABS16UW:
|
||||||
RL78_STACK_POP (relocation);
|
|
||||||
relocation >>= 1;
|
|
||||||
RANGE (0, 65536);
|
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:
|
||||||
RL78_STACK_POP (relocation);
|
|
||||||
RANGE (-128, 255);
|
RANGE (-128, 255);
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_ABS8U:
|
case R_RL78_ABS8U:
|
||||||
RL78_STACK_POP (relocation);
|
|
||||||
RANGE (0, 255);
|
|
||||||
OP (0) = relocation;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_ABS8UL:
|
case R_RL78_ABS8UL:
|
||||||
RL78_STACK_POP (relocation);
|
|
||||||
relocation >>= 2;
|
|
||||||
RANGE (0, 255);
|
|
||||||
OP (0) = relocation;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_ABS8UW:
|
case R_RL78_ABS8UW:
|
||||||
RL78_STACK_POP (relocation);
|
|
||||||
relocation >>= 1;
|
|
||||||
RANGE (0, 255);
|
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:
|
||||||
RL78_STACK_POP (relocation);
|
|
||||||
RANGE (-128, 127);
|
RANGE (-128, 127);
|
||||||
OP (0) = relocation;
|
OP (0) = relocation;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case R_RL78_SYM:
|
case R_RL78_SYM:
|
||||||
if (r_symndx < symtab_hdr->sh_info)
|
if (r_symndx < symtab_hdr->sh_info)
|
||||||
RL78_STACK_PUSH (sec->output_section->vma
|
relocation = sec->output_section->vma + sec->output_offset
|
||||||
+ sec->output_offset
|
+ sym->st_value + rel->r_addend;
|
||||||
+ sym->st_value
|
else if (h != NULL
|
||||||
+ rel->r_addend);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (h != NULL
|
|
||||||
&& (h->root.type == bfd_link_hash_defined
|
&& (h->root.type == bfd_link_hash_defined
|
||||||
|| h->root.type == bfd_link_hash_defweak))
|
|| h->root.type == bfd_link_hash_defweak))
|
||||||
RL78_STACK_PUSH (h->root.u.def.value
|
relocation = h->root.u.def.value
|
||||||
+ sec->output_section->vma
|
+ sec->output_section->vma
|
||||||
+ sec->output_offset
|
+ sec->output_offset
|
||||||
+ rel->r_addend);
|
+ rel->r_addend;
|
||||||
else if (h->root.type == bfd_link_hash_undefweak)
|
|
||||||
RL78_STACK_PUSH (0);
|
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
relocation = 0;
|
||||||
|
if (h->root.type != bfd_link_hash_undefweak)
|
||||||
_bfd_error_handler (_("Warning: RL78_SYM reloc with an unknown symbol"));
|
_bfd_error_handler (_("Warning: RL78_SYM reloc with an unknown symbol"));
|
||||||
}
|
}
|
||||||
break;
|
(void) rl78_compute_complex_reloc (r_type, relocation, input_section);
|
||||||
|
|
||||||
case R_RL78_OPneg:
|
|
||||||
{
|
|
||||||
int32_t tmp;
|
|
||||||
|
|
||||||
RL78_STACK_POP (tmp);
|
|
||||||
tmp = - tmp;
|
|
||||||
RL78_STACK_PUSH (tmp);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPadd:
|
|
||||||
{
|
|
||||||
int32_t tmp1, tmp2;
|
|
||||||
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
tmp1 += tmp2;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPsub:
|
|
||||||
{
|
|
||||||
int32_t tmp1, tmp2;
|
|
||||||
|
|
||||||
/* For the expression "A - B", the assembler pushes A,
|
|
||||||
then B, then OPSUB. So the first op we pop is B, not
|
|
||||||
A. */
|
|
||||||
RL78_STACK_POP (tmp2); /* B */
|
|
||||||
RL78_STACK_POP (tmp1); /* A */
|
|
||||||
tmp1 -= tmp2; /* A - B */
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPmul:
|
|
||||||
{
|
|
||||||
int32_t tmp1, tmp2;
|
|
||||||
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
tmp1 *= tmp2;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPdiv:
|
|
||||||
{
|
|
||||||
int32_t tmp1, tmp2;
|
|
||||||
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
tmp1 /= tmp2;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPshla:
|
|
||||||
{
|
|
||||||
int32_t tmp1, tmp2;
|
|
||||||
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
tmp1 <<= tmp2;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPshra:
|
|
||||||
{
|
|
||||||
int32_t tmp1, tmp2;
|
|
||||||
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
tmp1 >>= tmp2;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPsctsize:
|
|
||||||
RL78_STACK_PUSH (input_section->size);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPscttop:
|
|
||||||
RL78_STACK_PUSH (input_section->output_section->vma);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPand:
|
|
||||||
{
|
|
||||||
int32_t tmp1, tmp2;
|
|
||||||
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
tmp1 &= tmp2;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPor:
|
|
||||||
{
|
|
||||||
int32_t tmp1, tmp2;
|
|
||||||
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
tmp1 |= tmp2;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPxor:
|
|
||||||
{
|
|
||||||
int32_t tmp1, tmp2;
|
|
||||||
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
tmp1 ^= tmp2;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPnot:
|
|
||||||
{
|
|
||||||
int32_t tmp;
|
|
||||||
|
|
||||||
RL78_STACK_POP (tmp);
|
|
||||||
tmp = ~ tmp;
|
|
||||||
RL78_STACK_PUSH (tmp);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPmod:
|
|
||||||
{
|
|
||||||
int32_t tmp1, tmp2;
|
|
||||||
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
tmp1 %= tmp2;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_OPromtop:
|
case R_RL78_OPromtop:
|
||||||
RL78_STACK_PUSH (get_romstart (&r, info, input_bfd, input_section, rel->r_offset));
|
relocation = get_romstart (&r, info, input_bfd, input_section, rel->r_offset);
|
||||||
|
(void) rl78_compute_complex_reloc (r_type, relocation, input_section);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_OPramtop:
|
case R_RL78_OPramtop:
|
||||||
RL78_STACK_PUSH (get_ramstart (&r, info, input_bfd, input_section, rel->r_offset));
|
relocation = get_ramstart (&r, info, input_bfd, input_section, rel->r_offset);
|
||||||
|
(void) rl78_compute_complex_reloc (r_type, relocation, input_section);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1703,7 +1841,6 @@ rl78_offset_for_reloc (bfd * abfd,
|
||||||
int * scale)
|
int * scale)
|
||||||
{
|
{
|
||||||
bfd_vma symval;
|
bfd_vma symval;
|
||||||
bfd_reloc_status_type r;
|
|
||||||
|
|
||||||
*scale = 1;
|
*scale = 1;
|
||||||
|
|
||||||
|
@ -1712,7 +1849,7 @@ rl78_offset_for_reloc (bfd * abfd,
|
||||||
gets a pointer to the last relocation used. */
|
gets a pointer to the last relocation used. */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
int32_t tmp1, tmp2;
|
unsigned long r_type;
|
||||||
|
|
||||||
/* Get the value of the symbol referred to by the reloc. */
|
/* Get the value of the symbol referred to by the reloc. */
|
||||||
if (ELF32_R_SYM (rel->r_info) < symtab_hdr->sh_info)
|
if (ELF32_R_SYM (rel->r_info) < symtab_hdr->sh_info)
|
||||||
|
@ -1786,135 +1923,57 @@ rl78_offset_for_reloc (bfd * abfd,
|
||||||
symval += rel->r_addend;
|
symval += rel->r_addend;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ELF32_R_TYPE (rel->r_info))
|
r_type = ELF32_R_TYPE (rel->r_info);
|
||||||
|
switch (r_type)
|
||||||
{
|
{
|
||||||
case R_RL78_SYM:
|
case R_RL78_SYM:
|
||||||
RL78_STACK_PUSH (symval);
|
(void) rl78_compute_complex_reloc (r_type, symval, input_section);
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPneg:
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
tmp1 = - tmp1;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPadd:
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
tmp1 += tmp2;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPsub:
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
tmp2 -= tmp1;
|
|
||||||
RL78_STACK_PUSH (tmp2);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPmul:
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
tmp1 *= tmp2;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPdiv:
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
tmp1 /= tmp2;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPshla:
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
tmp1 <<= tmp2;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPshra:
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
tmp1 >>= tmp2;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPsctsize:
|
|
||||||
RL78_STACK_PUSH (input_section->size);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPscttop:
|
|
||||||
RL78_STACK_PUSH (input_section->output_section->vma);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPand:
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
tmp1 &= tmp2;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPor:
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
tmp1 |= tmp2;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPxor:
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
tmp1 ^= tmp2;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPnot:
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
tmp1 = ~ tmp1;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case R_RL78_OPmod:
|
|
||||||
RL78_STACK_POP (tmp1);
|
|
||||||
RL78_STACK_POP (tmp2);
|
|
||||||
tmp1 %= tmp2;
|
|
||||||
RL78_STACK_PUSH (tmp1);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_OPromtop:
|
case R_RL78_OPromtop:
|
||||||
RL78_STACK_PUSH (get_romstart (&r, info, input_bfd, input_section, rel->r_offset));
|
symval = get_romstart (NULL, info, input_bfd, input_section, rel->r_offset);
|
||||||
|
(void) rl78_compute_complex_reloc (r_type, symval, input_section);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_OPramtop:
|
case R_RL78_OPramtop:
|
||||||
RL78_STACK_PUSH (get_ramstart (&r, info, input_bfd, input_section, rel->r_offset));
|
symval = get_ramstart (NULL, info, input_bfd, input_section, rel->r_offset);
|
||||||
|
(void) rl78_compute_complex_reloc (r_type, symval, input_section);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case R_RL78_OPneg:
|
||||||
|
case R_RL78_OPadd:
|
||||||
|
case R_RL78_OPsub:
|
||||||
|
case R_RL78_OPmul:
|
||||||
|
case R_RL78_OPdiv:
|
||||||
|
case R_RL78_OPshla:
|
||||||
|
case R_RL78_OPshra:
|
||||||
|
case R_RL78_OPsctsize:
|
||||||
|
case R_RL78_OPscttop:
|
||||||
|
case R_RL78_OPand:
|
||||||
|
case R_RL78_OPor:
|
||||||
|
case R_RL78_OPxor:
|
||||||
|
case R_RL78_OPnot:
|
||||||
|
case R_RL78_OPmod:
|
||||||
|
(void) rl78_compute_complex_reloc (r_type, 0, input_section);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_RL78_DIR16UL:
|
case R_RL78_DIR16UL:
|
||||||
case R_RL78_DIR8UL:
|
case R_RL78_DIR8UL:
|
||||||
case R_RL78_ABS16UL:
|
case R_RL78_ABS16UL:
|
||||||
case R_RL78_ABS8UL:
|
case R_RL78_ABS8UL:
|
||||||
if (rl78_stack_top)
|
|
||||||
RL78_STACK_POP (symval);
|
|
||||||
if (lrel)
|
|
||||||
*lrel = rel;
|
|
||||||
*scale = 4;
|
*scale = 4;
|
||||||
return symval;
|
goto reloc_computes_value;
|
||||||
|
|
||||||
case R_RL78_DIR16UW:
|
case R_RL78_DIR16UW:
|
||||||
case R_RL78_DIR8UW:
|
case R_RL78_DIR8UW:
|
||||||
case R_RL78_ABS16UW:
|
case R_RL78_ABS16UW:
|
||||||
case R_RL78_ABS8UW:
|
case R_RL78_ABS8UW:
|
||||||
if (rl78_stack_top)
|
|
||||||
RL78_STACK_POP (symval);
|
|
||||||
if (lrel)
|
|
||||||
*lrel = rel;
|
|
||||||
*scale = 2;
|
*scale = 2;
|
||||||
return symval;
|
goto reloc_computes_value;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (rl78_stack_top)
|
reloc_computes_value:
|
||||||
RL78_STACK_POP (symval);
|
symval = rl78_compute_complex_reloc (r_type, 0, input_section);
|
||||||
if (lrel)
|
if (lrel)
|
||||||
*lrel = rel;
|
*lrel = rel;
|
||||||
return symval;
|
return symval;
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
2015-04-14 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
* readelf.c (target_specific_reloc_handling): Add code to handle
|
||||||
|
RL78 complex relocs.
|
||||||
|
|
||||||
2015-04-13 Doug Evans <dje@google.com>
|
2015-04-13 Doug Evans <dje@google.com>
|
||||||
|
|
||||||
PR binutils/18218
|
PR binutils/18218
|
||||||
|
|
|
@ -11161,6 +11161,42 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case EM_RL78:
|
||||||
|
{
|
||||||
|
static bfd_vma saved_sym1 = 0;
|
||||||
|
static bfd_vma saved_sym2 = 0;
|
||||||
|
static bfd_vma value;
|
||||||
|
|
||||||
|
switch (reloc_type)
|
||||||
|
{
|
||||||
|
case 0x80: /* R_RL78_SYM. */
|
||||||
|
saved_sym1 = saved_sym2;
|
||||||
|
saved_sym2 = symtab[get_reloc_symindex (reloc->r_info)].st_value;
|
||||||
|
saved_sym2 += reloc->r_addend;
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case 0x83: /* R_RL78_OPsub. */
|
||||||
|
value = saved_sym1 - saved_sym2;
|
||||||
|
saved_sym2 = saved_sym1 = 0;
|
||||||
|
return TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x41: /* R_RL78_ABS32. */
|
||||||
|
byte_put (start + reloc->r_offset, value, 4);
|
||||||
|
value = 0;
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case 0x43: /* R_RL78_ABS16. */
|
||||||
|
byte_put (start + reloc->r_offset, value, 2);
|
||||||
|
value = 0;
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
2015-04-14 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
* config/tc-rl78.h (TC_LINKRELAX_FIXUP): Define.
|
||||||
|
(TC_FORCE_RELOCATION_SUB_SAME): Define.
|
||||||
|
(DWARF2_USE_FIXED_ADVANCE_PC): Define.
|
||||||
|
|
||||||
2015-04-10 Nick Clifton <nickc@redhat.com>
|
2015-04-10 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
PR binutils/18198
|
PR binutils/18198
|
||||||
|
|
|
@ -340,15 +340,16 @@ md_parse_option (int c, char * arg ATTRIBUTE_UNUSED)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
|
md_show_usage (FILE * stream)
|
||||||
{
|
{
|
||||||
fprintf (stream, _(" RL78 specific command line options:\n"));
|
fprintf (stream, _(" RL78 specific command line options:\n"));
|
||||||
|
fprintf (stream, _(" --mrelax Enable link time relaxation\n"));
|
||||||
fprintf (stream, _(" --mg10 Enable support for G10 variant\n"));
|
fprintf (stream, _(" --mg10 Enable support for G10 variant\n"));
|
||||||
fprintf (stream, _(" --mg13 Selects the G13 core.\n"));
|
fprintf (stream, _(" --mg13 Selects the G13 core.\n"));
|
||||||
fprintf (stream, _(" --mg14 Selects the G14 core [default]\n"));
|
fprintf (stream, _(" --mg14 Selects the G14 core [default]\n"));
|
||||||
fprintf (stream, _(" --mrl78 Alias for --mg14\n"));
|
fprintf (stream, _(" --mrl78 Alias for --mg14\n"));
|
||||||
fprintf (stream, _(" --m32bit-doubles [default]\n"));
|
fprintf (stream, _(" --m32bit-doubles [default]\n"));
|
||||||
fprintf (stream, _(" --m64bit-doubles\n"));
|
fprintf (stream, _(" --m64bit-doubles Source code uses 64-bit doubles\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -662,12 +663,22 @@ rl78_cons_fix_new (fragS * frag,
|
||||||
case BFD_RELOC_RL78_LO16:
|
case BFD_RELOC_RL78_LO16:
|
||||||
case BFD_RELOC_RL78_HI16:
|
case BFD_RELOC_RL78_HI16:
|
||||||
if (size != 2)
|
if (size != 2)
|
||||||
|
{
|
||||||
|
/* Fixups to assembler generated expressions do not use %hi or %lo. */
|
||||||
|
if (frag->fr_file)
|
||||||
as_bad (_("%%hi16/%%lo16 only applies to .short or .hword"));
|
as_bad (_("%%hi16/%%lo16 only applies to .short or .hword"));
|
||||||
|
}
|
||||||
|
else
|
||||||
type = exp->X_md;
|
type = exp->X_md;
|
||||||
break;
|
break;
|
||||||
case BFD_RELOC_RL78_HI8:
|
case BFD_RELOC_RL78_HI8:
|
||||||
if (size != 1)
|
if (size != 1)
|
||||||
|
{
|
||||||
|
/* Fixups to assembler generated expressions do not use %hi or %lo. */
|
||||||
|
if (frag->fr_file)
|
||||||
as_bad (_("%%hi8 only applies to .byte"));
|
as_bad (_("%%hi8 only applies to .byte"));
|
||||||
|
}
|
||||||
|
else
|
||||||
type = exp->X_md;
|
type = exp->X_md;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -823,7 +834,7 @@ rl78_frag_fix_value (fragS * fragP,
|
||||||
/* Estimate how big the opcode is after this relax pass. The return
|
/* Estimate how big the opcode is after this relax pass. The return
|
||||||
value is the difference between fr_fix and the actual size. We
|
value is the difference between fr_fix and the actual size. We
|
||||||
compute the total size in rl78_relax_frag and store it in fr_subtype,
|
compute the total size in rl78_relax_frag and store it in fr_subtype,
|
||||||
sowe only need to subtract fx_fix and return it. */
|
so we only need to subtract fx_fix and return it. */
|
||||||
|
|
||||||
int
|
int
|
||||||
md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, segT segment ATTRIBUTE_UNUSED)
|
md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, segT segment ATTRIBUTE_UNUSED)
|
||||||
|
@ -960,7 +971,7 @@ rl78_relax_frag (segT segment ATTRIBUTE_UNUSED, fragS * fragP, long stretch)
|
||||||
fragP->fr_subtype = newsize;
|
fragP->fr_subtype = newsize;
|
||||||
tprintf (" -> new %d old %d delta %d\n", newsize, oldsize, newsize-oldsize);
|
tprintf (" -> new %d old %d delta %d\n", newsize, oldsize, newsize-oldsize);
|
||||||
return newsize - oldsize;
|
return newsize - oldsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This lets us test for the opcode type and the desired size in a
|
/* This lets us test for the opcode type and the desired size in a
|
||||||
switch statement. */
|
switch statement. */
|
||||||
|
|
|
@ -85,3 +85,17 @@ extern void rl78_elf_final_processing (void);
|
||||||
|
|
||||||
#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \
|
#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) \
|
||||||
((EXP)->X_md = 0, expression (EXP), TC_PARSE_CONS_RETURN_NONE)
|
((EXP)->X_md = 0, expression (EXP), TC_PARSE_CONS_RETURN_NONE)
|
||||||
|
|
||||||
|
#define TC_LINKRELAX_FIXUP(seg) ((seg->flags & SEC_CODE) || (seg->flags & SEC_DEBUGGING))
|
||||||
|
|
||||||
|
/* Do not adjust relocations involving symbols in code sections,
|
||||||
|
because it breaks linker relaxations. This could be fixed in the
|
||||||
|
linker, but this fix is simpler, and it pretty much only affects
|
||||||
|
object size a little bit. */
|
||||||
|
#define TC_FORCE_RELOCATION_SUB_SAME(FIX, SEC) \
|
||||||
|
( ((SEC)->flags & SEC_CODE) != 0 \
|
||||||
|
|| ((SEC)->flags & SEC_DEBUGGING) != 0 \
|
||||||
|
|| ! SEG_NORMAL (SEC) \
|
||||||
|
|| TC_FORCE_RELOCATION (FIX))
|
||||||
|
|
||||||
|
#define DWARF2_USE_FIXED_ADVANCE_PC 1
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
2015-04-14 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
* gas/lns/lns.exp: Add RL78 to list of targets using
|
||||||
|
DW_LNS_fixed_advance_pc.
|
||||||
|
|
||||||
2015-04-08 H.J. Lu <hongjiu.lu@intel.com>
|
2015-04-08 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
* gas/i386/dw2-compressed-1.d: New file.
|
* gas/i386/dw2-compressed-1.d: New file.
|
||||||
|
|
|
@ -32,13 +32,14 @@ if {
|
||||||
&& ![istarget s390*-*-*]
|
&& ![istarget s390*-*-*]
|
||||||
} {
|
} {
|
||||||
# Use alternate file for targets using DW_LNS_fixed_advance_pc opcodes.
|
# Use alternate file for targets using DW_LNS_fixed_advance_pc opcodes.
|
||||||
if { [istarget xtensa*-*-*]
|
if { [istarget am3*-*-*]
|
||||||
|| [istarget am3*-*-*]
|
|
||||||
|| [istarget cr16-*-*]
|
|| [istarget cr16-*-*]
|
||||||
|| [istarget crx-*-*]
|
|| [istarget crx-*-*]
|
||||||
|
|| [istarget mn10*-*-*]
|
||||||
|| [istarget msp430-*-*]
|
|| [istarget msp430-*-*]
|
||||||
|| [istarget nds32*-*-*]
|
|| [istarget nds32*-*-*]
|
||||||
|| [istarget mn10*-*-*] } {
|
|| [istarget rl78-*-*]
|
||||||
|
|| [istarget xtensa*-*-*] } {
|
||||||
run_dump_test "lns-common-1-alt"
|
run_dump_test "lns-common-1-alt"
|
||||||
run_dump_test "lns-big-delta"
|
run_dump_test "lns-big-delta"
|
||||||
} elseif { [istarget ia64*-*-*] } {
|
} elseif { [istarget ia64*-*-*] } {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue