aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-s12z.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elf32-s12z.c')
-rw-r--r--bfd/elf32-s12z.c270
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"