diff options
Diffstat (limited to 'bfd/elf32-s12z.c')
-rw-r--r-- | bfd/elf32-s12z.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/bfd/elf32-s12z.c b/bfd/elf32-s12z.c new file mode 100644 index 0000000..4b638e6 --- /dev/null +++ b/bfd/elf32-s12z.c @@ -0,0 +1,270 @@ +/* Freescale S12Z-specific support for 32-bit ELF + Copyright (C) 1999-2018 Free Software Foundation, Inc. + (Heavily copied from the D10V port by Martin Hunt (hunt@cygnus.com)) + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "sysdep.h" +#include "bfd.h" +#include "bfdlink.h" +#include "libbfd.h" +#include "elf-bfd.h" + +#include "elf/s12z.h" + +/* Relocation functions. */ +static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup + (bfd *, bfd_reloc_code_real_type); +static bfd_boolean s12z_info_to_howto_rel + (bfd *, arelent *, Elf_Internal_Rela *); + +static bfd_reloc_status_type +shift_addend_reloc (bfd *abfd, arelent *reloc_entry, struct bfd_symbol *symbol ATTRIBUTE_UNUSED, + void *data ATTRIBUTE_UNUSED, asection *input_section ATTRIBUTE_UNUSED, + bfd *output ATTRIBUTE_UNUSED, char **msg ATTRIBUTE_UNUSED) +{ + /* This is a really peculiar reloc, which is done for compatibility + with the Freescale toolchain. + + That toolchain appears to (ab)use the lowest 15 bits of the addend for + the purpose of holding flags. The purpose of these flags are unknown. + So in this function, when writing the bfd we left shift the addend by + 15, and when reading we right shift it by 15 (discarding the lower bits). + + This allows the linker to work with object files generated by Freescale, + as well as by Gas. */ + + if (abfd->is_linker_input) + reloc_entry->addend >>= 15; + else + reloc_entry->addend <<= 15; + + return bfd_reloc_continue; +} + +#define USE_REL 0 + +static reloc_howto_type elf_s12z_howto_table[] = +{ + /* This reloc does nothing. */ + HOWTO (R_S12Z_NONE, /* type */ + 0, /* rightshift */ + 3, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_S12Z_NONE", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 24 bit absolute relocation emitted by the OPR mode operands */ + HOWTO (R_S12Z_OPR, /* type */ + 0, /* rightshift */ + 5, /* size (0 = byte, 1 = short, 2 = long) */ + 24, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + shift_addend_reloc, + "R_S12Z_OPR", /* name */ + FALSE, /* partial_inplace */ + 0x00ffffff, /* src_mask */ + 0x00ffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* The purpose of this reloc is not known */ + HOWTO (R_S12Z_UKNWN_2, /* type */ + 0, /* rightshift */ + 3, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_S12Z_UKNWN_2", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 15 bit PC-rel relocation */ + HOWTO (R_S12Z_PCREL_7_15, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 15, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + shift_addend_reloc, + "R_S12Z_PCREL_7_15", /* name */ + FALSE, /* partial_inplace */ + 0x00, /* src_mask */ + 0x007fff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + /* A 24 bit absolute relocation emitted by EXT24 mode operands */ + HOWTO (R_S12Z_EXT24, /* type */ + 0, /* rightshift */ + 5, /* size (0 = byte, 1 = short, 2 = long) */ + 24, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_S12Z_EXT24", /* name */ + FALSE, /* partial_inplace */ + 0x00ffffff, /* src_mask */ + 0x00ffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* The purpose of this reloc is not known */ + HOWTO (R_S12Z_UKNWN_3, /* type */ + 0, /* rightshift */ + 3, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_S12Z_UKNWN_3", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 32 bit absolute relocation */ + HOWTO (R_S12Z_EXT32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_S12Z_EXT32", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ +}; + +/* Map BFD reloc types to S12Z ELF reloc types. */ + +struct s12z_reloc_map +{ + bfd_reloc_code_real_type bfd_reloc_val; + unsigned char elf_reloc_val; +}; + +static const struct s12z_reloc_map s12z_reloc_map[] = +{ + /* bfd reloc val */ /* elf reloc val */ + {BFD_RELOC_NONE, R_S12Z_NONE}, + {BFD_RELOC_32, R_S12Z_EXT32}, + {BFD_RELOC_24, R_S12Z_EXT24}, + {BFD_RELOC_16_PCREL, R_S12Z_PCREL_7_15} +}; + +static reloc_howto_type * +bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, + bfd_reloc_code_real_type code) +{ + unsigned int i; + + for (i = 0; + i < sizeof (s12z_reloc_map) / sizeof (struct s12z_reloc_map); + i++) + { + if (s12z_reloc_map[i].bfd_reloc_val == code) + { + return &elf_s12z_howto_table[s12z_reloc_map[i].elf_reloc_val]; + } + } + + printf ("%s:%d Not found type %d\n", __FILE__, __LINE__, code); + + return NULL; +} + +static reloc_howto_type * +bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + const char *r_name) +{ + unsigned int i; + + printf ("%s:%d Looking up %s\n", __FILE__, __LINE__, r_name); + + for (i = 0; + i < (sizeof (elf_s12z_howto_table) + / sizeof (elf_s12z_howto_table[0])); + i++) + if (elf_s12z_howto_table[i].name != NULL + && strcasecmp (elf_s12z_howto_table[i].name, r_name) == 0) + return &elf_s12z_howto_table[i]; + + return NULL; +} + +/* Set the howto pointer for an S12Z ELF reloc. */ + +static bfd_boolean +s12z_info_to_howto_rel (bfd *abfd, + arelent *cache_ptr, Elf_Internal_Rela *dst) +{ + unsigned int r_type = ELF32_R_TYPE (dst->r_info); + + if (r_type >= (unsigned int) R_S12Z_max) + { + /* xgettext:c-format */ + _bfd_error_handler (_("%pB: unsupported relocation type %#x"), + abfd, r_type); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + + cache_ptr->howto = &elf_s12z_howto_table[r_type]; + return TRUE; +} + +static bfd_boolean +s12z_elf_set_mach_from_flags (bfd *abfd) +{ + bfd_default_set_arch_mach (abfd, bfd_arch_s12z, 0); // bfd_mach_s12z); + + return TRUE; +} + +#define ELF_ARCH bfd_arch_s12z +#define ELF_TARGET_ID 0 +#define ELF_MACHINE_CODE EM_S12Z +#define ELF_MAXPAGESIZE 0x1000 + +#define TARGET_BIG_SYM s12z_elf32_vec +#define TARGET_BIG_NAME "elf32-s12z" + +#define elf_info_to_howto NULL +#define elf_info_to_howto_rel s12z_info_to_howto_rel +#define elf_backend_object_p s12z_elf_set_mach_from_flags +#define elf_backend_final_write_processing NULL +#define elf_backend_can_gc_sections 1 + +#include "elf32-target.h" |