diff options
author | Nick Clifton <nickc@redhat.com> | 2015-04-14 16:23:33 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2015-04-14 16:23:33 +0100 |
commit | 6ff71e768112317de1236a429e7c88c9d3e32116 (patch) | |
tree | 3d24e09232efe594ec6a32482a95b2f161250e4e /bfd | |
parent | 9e811bc379ef78f0e2beadda9ed3ce6679ded7ea (diff) | |
download | fsf-binutils-gdb-6ff71e768112317de1236a429e7c88c9d3e32116.zip fsf-binutils-gdb-6ff71e768112317de1236a429e7c88c9d3e32116.tar.gz fsf-binutils-gdb-6ff71e768112317de1236a429e7c88c9d3e32116.tar.bz2 |
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.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 18 | ||||
-rw-r--r-- | bfd/elf32-rl78.c | 835 |
2 files changed, 465 insertions, 388 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 056833e..49202af 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -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> PR ld/pr17709 diff --git a/bfd/elf32-rl78.c b/bfd/elf32-rl78.c index 70b49aa..2822547 100644 --- a/bfd/elf32-rl78.c +++ b/bfd/elf32-rl78.c @@ -31,6 +31,14 @@ HOWTO (R_RL78_##n, shift, sz, bit, pcrel, 0, complain_overflow_ ## complain, \ 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; feel free to move them as needed to avoid conflicts with published relocation numbers. */ @@ -106,23 +114,23 @@ static reloc_howto_type rl78_elf_howto_table [] = EMPTY_HOWTO (0x3f), EMPTY_HOWTO (0x40), - RL78REL (ABS32, 2, 32, 0, dont, FALSE), - RL78REL (ABS24S, 2, 24, 0, signed, FALSE), - RL78REL (ABS16, 1, 16, 0, dont, FALSE), - RL78REL (ABS16U, 1, 16, 0, unsigned, FALSE), - RL78REL (ABS16S, 1, 16, 0, signed, FALSE), - RL78REL (ABS8, 0, 8, 0, dont, FALSE), - RL78REL (ABS8U, 0, 8, 0, unsigned, FALSE), - RL78REL (ABS8S, 0, 8, 0, signed, FALSE), - RL78REL (ABS24S_PCREL, 2, 24, 0, signed, TRUE), - RL78REL (ABS16S_PCREL, 1, 16, 0, signed, TRUE), - RL78REL (ABS8S_PCREL, 0, 8, 0, signed, TRUE), - RL78REL (ABS16UL, 1, 16, 0, unsigned, FALSE), - RL78REL (ABS16UW, 1, 16, 0, unsigned, FALSE), - RL78REL (ABS8UL, 0, 8, 0, unsigned, FALSE), - RL78REL (ABS8UW, 0, 8, 0, unsigned, FALSE), - RL78REL (ABS32_REV, 2, 32, 0, dont, FALSE), - RL78REL (ABS16_REV, 1, 16, 0, dont, FALSE), + RL78_OP_REL (ABS32, 2, 32, 0, dont, FALSE), + RL78_OP_REL (ABS24S, 2, 24, 0, signed, FALSE), + RL78_OP_REL (ABS16, 1, 16, 0, dont, FALSE), + RL78_OP_REL (ABS16U, 1, 16, 0, unsigned, FALSE), + RL78_OP_REL (ABS16S, 1, 16, 0, signed, FALSE), + RL78_OP_REL (ABS8, 0, 8, 0, dont, FALSE), + RL78_OP_REL (ABS8U, 0, 8, 0, unsigned, FALSE), + RL78_OP_REL (ABS8S, 0, 8, 0, signed, FALSE), + RL78_OP_REL (ABS24S_PCREL, 2, 24, 0, signed, TRUE), + RL78_OP_REL (ABS16S_PCREL, 1, 16, 0, signed, TRUE), + RL78_OP_REL (ABS8S_PCREL, 0, 8, 0, signed, TRUE), + RL78_OP_REL (ABS16UL, 1, 16, 0, unsigned, FALSE), + RL78_OP_REL (ABS16UW, 1, 16, 0, unsigned, FALSE), + RL78_OP_REL (ABS8UL, 0, 8, 0, unsigned, FALSE), + RL78_OP_REL (ABS8UW, 0, 8, 0, unsigned, FALSE), + RL78_OP_REL (ABS32_REV, 2, 32, 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) @@ -174,29 +182,29 @@ static reloc_howto_type rl78_elf_howto_table [] = EMPTY_HOWTO (0x7e), EMPTY_HOWTO (0x7f), - RL78REL (SYM, 2, 32, 0, dont, FALSE), - RL78REL (OPneg, 2, 32, 0, dont, FALSE), - RL78REL (OPadd, 2, 32, 0, dont, FALSE), - RL78REL (OPsub, 2, 32, 0, dont, FALSE), - RL78REL (OPmul, 2, 32, 0, dont, FALSE), - RL78REL (OPdiv, 2, 32, 0, dont, FALSE), - RL78REL (OPshla, 2, 32, 0, dont, FALSE), - RL78REL (OPshra, 2, 32, 0, dont, FALSE), - RL78REL (OPsctsize, 2, 32, 0, dont, FALSE), + RL78_OP_REL (SYM, 2, 32, 0, dont, FALSE), + RL78_OP_REL (OPneg, 2, 32, 0, dont, FALSE), + RL78_OP_REL (OPadd, 2, 32, 0, dont, FALSE), + RL78_OP_REL (OPsub, 2, 32, 0, dont, FALSE), + RL78_OP_REL (OPmul, 2, 32, 0, dont, FALSE), + RL78_OP_REL (OPdiv, 2, 32, 0, dont, FALSE), + RL78_OP_REL (OPshla, 2, 32, 0, dont, FALSE), + RL78_OP_REL (OPshra, 2, 32, 0, dont, FALSE), + RL78_OP_REL (OPsctsize, 2, 32, 0, dont, FALSE), EMPTY_HOWTO (0x89), EMPTY_HOWTO (0x8a), EMPTY_HOWTO (0x8b), EMPTY_HOWTO (0x8c), - RL78REL (OPscttop, 2, 32, 0, dont, FALSE), + RL78_OP_REL (OPscttop, 2, 32, 0, dont, FALSE), EMPTY_HOWTO (0x8e), EMPTY_HOWTO (0x8f), - RL78REL (OPand, 2, 32, 0, dont, FALSE), - RL78REL (OPor, 2, 32, 0, dont, FALSE), - RL78REL (OPxor, 2, 32, 0, dont, FALSE), - RL78REL (OPnot, 2, 32, 0, dont, FALSE), - RL78REL (OPmod, 2, 32, 0, dont, FALSE), - RL78REL (OPromtop, 2, 32, 0, dont, FALSE), - RL78REL (OPramtop, 2, 32, 0, dont, FALSE) + RL78_OP_REL (OPand, 2, 32, 0, dont, FALSE), + RL78_OP_REL (OPor, 2, 32, 0, dont, FALSE), + RL78_OP_REL (OPxor, 2, 32, 0, dont, FALSE), + RL78_OP_REL (OPnot, 2, 32, 0, dont, FALSE), + RL78_OP_REL (OPmod, 2, 32, 0, dont, FALSE), + RL78_OP_REL (OPromtop, 2, 32, 0, dont, FALSE), + RL78_OP_REL (OPramtop, 2, 32, 0, dont, FALSE) }; /* Map BFD reloc types to RL78 ELF reloc types. */ @@ -292,22 +300,29 @@ get_symbol_value (const char * name, asection * input_section, int offset) { - bfd_vma value = 0; struct bfd_link_hash_entry * h; + if (info == NULL) + return 0; + h = bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, TRUE); if (h == NULL || (h->type != bfd_link_hash_defined && h->type != bfd_link_hash_defweak)) - * status = info->callbacks->undefined_symbol - (info, name, input_bfd, input_section, offset, TRUE); - else - value = (h->u.def.value - + h->u.def.section->output_section->vma - + h->u.def.section->output_offset); + { + bfd_reloc_status_type res; + + res = info->callbacks->undefined_symbol + (info, name, input_bfd, input_section, offset, TRUE); + if (status) + * status = res; + return 0; + } - return value; + return (h->u.def.value + + h->u.def.section->output_section->vma + + h->u.def.section->output_offset); } static bfd_vma @@ -319,12 +334,15 @@ get_romstart (bfd_reloc_status_type * status, { static bfd_boolean cached = FALSE; static bfd_vma cached_value = 0; + static bfd_reloc_status_type cached_status; 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; } + if (status) + * status = cached_status; return cached_value; } @@ -337,12 +355,15 @@ get_ramstart (bfd_reloc_status_type * status, { static bfd_boolean cached = FALSE; static bfd_vma cached_value = 0; + static bfd_reloc_status_type cached_status; 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; } + if (status) + * status = cached_status; return cached_value; } @@ -356,7 +377,7 @@ static unsigned int rl78_stack_top; if (rl78_stack_top < NUM_STACK_ENTRIES) \ rl78_stack [rl78_stack_top ++] = (val); \ else \ - r = bfd_reloc_dangerous; \ + _bfd_error_handler (_("Internal Error: RL78 reloc stack overflow")); \ } \ while (0) @@ -364,12 +385,269 @@ static unsigned int rl78_stack_top; do \ { \ if (rl78_stack_top > 0) \ - (dest) = rl78_stack [-- rl78_stack_top]; \ + (dest) = rl78_stack [-- rl78_stack_top];\ else \ - (dest) = 0, r = bfd_reloc_dangerous; \ + { \ + _bfd_error_handler (_("Internal Error: RL78 reloc stack underflow")); \ + (dest) = 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. 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], @@ -475,7 +753,7 @@ rl78_elf_relocate_section 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, rel, 1, relend, howto, 0, contents); @@ -559,8 +837,6 @@ rl78_elf_relocate_section r = bfd_reloc_ok; #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. */ switch (r_type) @@ -663,279 +939,141 @@ rl78_elf_relocate_section break; /* Complex reloc handling: */ - case R_RL78_ABS32: - RL78_STACK_POP (relocation); - OP (0) = relocation; - OP (1) = relocation >> 8; - OP (2) = relocation >> 16; - OP (3) = relocation >> 24; - break; - case R_RL78_ABS32_REV: - RL78_STACK_POP (relocation); - 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: - RL78_STACK_POP (relocation); - RANGE (-0x800000, 0x7fffff); - OP (0) = relocation; - OP (1) = relocation >> 8; - OP (2) = relocation >> 16; - break; - case R_RL78_ABS16: - RL78_STACK_POP (relocation); - RANGE (-32768, 65535); - OP (0) = relocation; - OP (1) = relocation >> 8; - break; - case R_RL78_ABS16_REV: - RL78_STACK_POP (relocation); - RANGE (-32768, 65535); - OP (1) = relocation; - OP (0) = relocation >> 8; - break; - case R_RL78_ABS16S_PCREL: case R_RL78_ABS16S: - RL78_STACK_POP (relocation); - RANGE (-32768, 32767); - OP (0) = relocation; - OP (1) = relocation >> 8; - break; - case R_RL78_ABS16U: - RL78_STACK_POP (relocation); - RANGE (0, 65536); - OP (0) = relocation; - OP (1) = relocation >> 8; - break; - 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: - RL78_STACK_POP (relocation); - relocation >>= 1; - RANGE (0, 65536); - OP (0) = relocation; - OP (1) = relocation >> 8; - break; - case R_RL78_ABS8: - RL78_STACK_POP (relocation); - RANGE (-128, 255); - OP (0) = relocation; - break; - case R_RL78_ABS8U: - RL78_STACK_POP (relocation); - RANGE (0, 255); - OP (0) = relocation; - break; - case R_RL78_ABS8UL: - RL78_STACK_POP (relocation); - relocation >>= 2; - RANGE (0, 255); - OP (0) = relocation; - break; - case R_RL78_ABS8UW: - RL78_STACK_POP (relocation); - relocation >>= 1; - RANGE (0, 255); - OP (0) = relocation; - break; - case R_RL78_ABS8S_PCREL: case R_RL78_ABS8S: - RL78_STACK_POP (relocation); - RANGE (-128, 127); - OP (0) = relocation; - break; - - case R_RL78_SYM: - if (r_symndx < symtab_hdr->sh_info) - RL78_STACK_PUSH (sec->output_section->vma - + sec->output_offset - + sym->st_value - + rel->r_addend); - else - { - if (h != NULL - && (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak)) - RL78_STACK_PUSH (h->root.u.def.value - + sec->output_section->vma - + sec->output_offset - + rel->r_addend); - else if (h->root.type == bfd_link_hash_undefweak) - RL78_STACK_PUSH (0); - else - _bfd_error_handler (_("Warning: RL78_SYM reloc with an unknown symbol")); - } - break; - 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; + 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); - RL78_STACK_POP (tmp2); - RL78_STACK_POP (tmp1); - tmp1 &= tmp2; - RL78_STACK_PUSH (tmp1); - } - break; + 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_OPor: - { - int32_t tmp1, tmp2; + case R_RL78_ABS32_REV: + OP (3) = relocation; + OP (2) = relocation >> 8; + OP (1) = relocation >> 16; + OP (0) = relocation >> 24; + break; - RL78_STACK_POP (tmp2); - RL78_STACK_POP (tmp1); - tmp1 |= tmp2; - RL78_STACK_PUSH (tmp1); - } - break; + case R_RL78_ABS24S_PCREL: + case R_RL78_ABS24S: + RANGE (-0x800000, 0x7fffff); + OP (0) = relocation; + OP (1) = relocation >> 8; + OP (2) = relocation >> 16; + break; - case R_RL78_OPxor: - { - int32_t tmp1, tmp2; + case R_RL78_ABS16: + RANGE (-32768, 65535); + OP (0) = relocation; + OP (1) = relocation >> 8; + break; - RL78_STACK_POP (tmp2); - RL78_STACK_POP (tmp1); - tmp1 ^= tmp2; - RL78_STACK_PUSH (tmp1); - } - break; + case R_RL78_ABS16_REV: + RANGE (-32768, 65535); + OP (1) = relocation; + OP (0) = relocation >> 8; + break; - case R_RL78_OPnot: - { - int32_t tmp; + case R_RL78_ABS16S_PCREL: + case R_RL78_ABS16S: + RANGE (-32768, 32767); + OP (0) = relocation; + OP (1) = relocation >> 8; + break; - RL78_STACK_POP (tmp); - tmp = ~ tmp; - RL78_STACK_PUSH (tmp); - } - break; + case R_RL78_ABS16U: + case R_RL78_ABS16UL: + case R_RL78_ABS16UW: + RANGE (0, 65536); + OP (0) = relocation; + OP (1) = relocation >> 8; + break; - case R_RL78_OPmod: - { - int32_t tmp1, tmp2; + case R_RL78_ABS8: + RANGE (-128, 255); + OP (0) = relocation; + break; - RL78_STACK_POP (tmp2); - RL78_STACK_POP (tmp1); - tmp1 %= tmp2; - RL78_STACK_PUSH (tmp1); - } + case R_RL78_ABS8U: + case R_RL78_ABS8UL: + case R_RL78_ABS8UW: + RANGE (0, 255); + OP (0) = relocation; + break; + + case R_RL78_ABS8S_PCREL: + case R_RL78_ABS8S: + RANGE (-128, 127); + OP (0) = relocation; + break; + + default: + break; + } + break; + + case R_RL78_SYM: + if (r_symndx < symtab_hdr->sh_info) + relocation = sec->output_section->vma + sec->output_offset + + sym->st_value + rel->r_addend; + else if (h != NULL + && (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak)) + relocation = h->root.u.def.value + + sec->output_section->vma + + sec->output_offset + + rel->r_addend; + else + { + relocation = 0; + if (h->root.type != bfd_link_hash_undefweak) + _bfd_error_handler (_("Warning: RL78_SYM reloc with an unknown symbol")); + } + (void) rl78_compute_complex_reloc (r_type, relocation, input_section); break; 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; 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; default: @@ -1688,22 +1826,21 @@ reloc_bubblesort (Elf_Internal_Rela * r, int count) #define OFFSET_FOR_RELOC(rel, lrel, scale) \ rl78_offset_for_reloc (abfd, rel + 1, symtab_hdr, shndx_buf, intsyms, \ - lrel, abfd, sec, link_info, scale) + lrel, abfd, sec, link_info, scale) static bfd_vma rl78_offset_for_reloc (bfd * abfd, - Elf_Internal_Rela * rel, - Elf_Internal_Shdr * symtab_hdr, - Elf_External_Sym_Shndx * shndx_buf ATTRIBUTE_UNUSED, - Elf_Internal_Sym * intsyms, - Elf_Internal_Rela ** lrel, - bfd * input_bfd, - asection * input_section, - struct bfd_link_info * info, - int * scale) + Elf_Internal_Rela * rel, + Elf_Internal_Shdr * symtab_hdr, + Elf_External_Sym_Shndx * shndx_buf ATTRIBUTE_UNUSED, + Elf_Internal_Sym * intsyms, + Elf_Internal_Rela ** lrel, + bfd * input_bfd, + asection * input_section, + struct bfd_link_info * info, + int * scale) { bfd_vma symval; - bfd_reloc_status_type r; *scale = 1; @@ -1712,7 +1849,7 @@ rl78_offset_for_reloc (bfd * abfd, gets a pointer to the last relocation used. */ while (1) { - int32_t tmp1, tmp2; + unsigned long r_type; /* Get the value of the symbol referred to by the reloc. */ 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; } - switch (ELF32_R_TYPE (rel->r_info)) + r_type = ELF32_R_TYPE (rel->r_info); + switch (r_type) { 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); + case R_RL78_OPromtop: + symval = get_romstart (NULL, info, input_bfd, input_section, rel->r_offset); + (void) rl78_compute_complex_reloc (r_type, symval, input_section); break; - case R_RL78_OPadd: - RL78_STACK_POP (tmp1); - RL78_STACK_POP (tmp2); - tmp1 += tmp2; - RL78_STACK_PUSH (tmp1); + case R_RL78_OPramtop: + 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: - 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; - - case R_RL78_OPromtop: - RL78_STACK_PUSH (get_romstart (&r, info, input_bfd, input_section, rel->r_offset)); - break; - - case R_RL78_OPramtop: - RL78_STACK_PUSH (get_ramstart (&r, info, input_bfd, input_section, rel->r_offset)); + (void) rl78_compute_complex_reloc (r_type, 0, input_section); break; case R_RL78_DIR16UL: case R_RL78_DIR8UL: case R_RL78_ABS16UL: case R_RL78_ABS8UL: - if (rl78_stack_top) - RL78_STACK_POP (symval); - if (lrel) - *lrel = rel; *scale = 4; - return symval; + goto reloc_computes_value; case R_RL78_DIR16UW: case R_RL78_DIR8UW: case R_RL78_ABS16UW: case R_RL78_ABS8UW: - if (rl78_stack_top) - RL78_STACK_POP (symval); - if (lrel) - *lrel = rel; *scale = 2; - return symval; - + goto reloc_computes_value; + default: - if (rl78_stack_top) - RL78_STACK_POP (symval); + reloc_computes_value: + symval = rl78_compute_complex_reloc (r_type, 0, input_section); if (lrel) *lrel = rel; return symval; |