aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-d30v.c
diff options
context:
space:
mode:
authorMartin Hunt <hunt@redhat.com>1997-02-19 01:29:29 +0000
committerMartin Hunt <hunt@redhat.com>1997-02-19 01:29:29 +0000
commitfd8d7c31c0b9b4fc9fa7ca9e6d38e4843cf2ff65 (patch)
treeabe5703a9b0967debc0e86ec178bd56ba9242a01 /bfd/elf32-d30v.c
parent49d1bbbef2a319214b111acb0090703061e4a702 (diff)
downloadgdb-fd8d7c31c0b9b4fc9fa7ca9e6d38e4843cf2ff65.zip
gdb-fd8d7c31c0b9b4fc9fa7ca9e6d38e4843cf2ff65.tar.gz
gdb-fd8d7c31c0b9b4fc9fa7ca9e6d38e4843cf2ff65.tar.bz2
Tue Feb 18 17:22:59 1997 Martin M. Hunt <hunt@pizza.cygnus.com>
* Makefile.in, archures.c, config.bfd, configure.in, elf.c, reloc.c, targets.c: New target, elf-*-D30V. * bfd-in2.h, configure, libbfd.h: Rebuilt. * cpu-d30v.c, elf32-d30v.c: New files.
Diffstat (limited to 'bfd/elf32-d30v.c')
-rw-r--r--bfd/elf32-d30v.c348
1 files changed, 348 insertions, 0 deletions
diff --git a/bfd/elf32-d30v.c b/bfd/elf32-d30v.c
new file mode 100644
index 0000000..bd13259
--- /dev/null
+++ b/bfd/elf32-d30v.c
@@ -0,0 +1,348 @@
+/* D30V-specific support for 32-bit ELF
+ Copyright (C) 1997 Free Software Foundation, Inc.
+ Contributed 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+
+static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
+ PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
+static void d30v_info_to_howto_rel
+ PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
+static bfd_reloc_status_type bfd_elf_d30v_reloc PARAMS ((
+ bfd *abfd,
+ arelent *reloc_entry,
+ asymbol *symbol,
+ PTR data,
+ asection *input_section,
+ bfd *output_bfd,
+ char **error_message));
+
+/* Use REL instead of RELA to save space */
+#define USE_REL
+
+enum reloc_type
+{
+ R_D30V_NONE = 0,
+ R_D30V_6,
+ R_D30V_15,
+ R_D30V_15_PCREL,
+ R_D30V_21,
+ R_D30V_21_PCREL,
+ R_D30V_32,
+ R_D30V_32_PCREL,
+ R_D30V_32_NORMAL,
+ R_D30V_max
+};
+
+static reloc_howto_type elf_d30v_howto_table[] =
+{
+ /* This reloc does nothing. */
+ HOWTO (R_D30V_NONE, /* 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_D30V_NONE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 6 bit absolute relocation */
+ HOWTO (R_D30V_6, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 6, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_D30V_6", /* name */
+ false, /* partial_inplace */
+ 0x3f, /* src_mask */
+ 0x3f, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* An absolute 15 bit relocation, right shifted by 3 */
+ HOWTO (R_D30V_15, /* type */
+ 3, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 15, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_D30V_15", /* name */
+ false, /* partial_inplace */
+ 0xfff, /* src_mask */
+ 0xfff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A relative 15 bit relocation, right shifted by 3 */
+ HOWTO (R_D30V_15_PCREL, /* type */
+ 3, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 15, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_D30V_15_PCREL", /* name */
+ false, /* partial_inplace */
+ 0xfff, /* src_mask */
+ 0xfff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* An absolute 21 bit relocation, right shifted by 3 */
+ HOWTO (R_D30V_21_PCREL, /* type */
+ 3, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 21, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_D30V_21", /* name */
+ false, /* partial_inplace */
+ 0x3ffff, /* src_mask */
+ 0x3ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A relative 21 bit relocation, right shifted by 3 */
+ HOWTO (R_D30V_21_PCREL, /* type */
+ 3, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 21, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_D30V_21_PCREL", /* name */
+ false, /* partial_inplace */
+ 0x3ffff, /* src_mask */
+ 0x3ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* A D30V 32 bit absolute relocation */
+ HOWTO (R_D30V_32, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_d30v_reloc, /* special_function */
+ "R_D30V_32", /* name */
+ false, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A relative 32 bit relocation */
+ HOWTO (R_D30V_32_PCREL, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_d30v_reloc, /* special_function */
+ "R_D30V_32_PCREL", /* name */
+ false, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* A regular 32 bit absolute relocation */
+ HOWTO (R_D30V_32_NORMAL, /* type */
+ 0, /* rightshift */
+ 4, /* 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_D30V_32_NORMAL", /* name */
+ false, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+};
+
+static bfd_reloc_status_type
+bfd_elf_d30v_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ bfd_vma relocation;
+ bfd_vma in1, in2;
+ bfd_reloc_status_type r;
+ asection *reloc_target_output_section;
+ bfd_size_type addr = reloc_entry->address;
+ bfd_reloc_status_type flag = bfd_reloc_ok;
+ bfd_vma output_base = 0;
+ reloc_howto_type *howto = reloc_entry->howto;
+
+ r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
+ input_section, output_bfd, error_message);
+ if (r != bfd_reloc_continue)
+ return r;
+
+ /* a hacked-up version of bfd_perform_reloc() follows */
+
+ /* Is the address of the relocation really within the section? */
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ /* Work out which section the relocation is targetted at and the
+ initial relocation command value. */
+
+ /* Get symbol value. (Common symbols are special.) */
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+
+
+ reloc_target_output_section = symbol->section->output_section;
+
+ /* Convert input-section-relative symbol value to absolute. */
+ if (output_bfd)
+ output_base = 0;
+ else
+ output_base = reloc_target_output_section->vma;
+
+ relocation += output_base + symbol->section->output_offset;
+
+ /* Add in supplied addend. */
+ relocation += reloc_entry->addend;
+
+ /* Here the variable relocation holds the final address of the
+ symbol we are relocating against, plus any addend. */
+
+ if (howto->pc_relative == true)
+ {
+ relocation -= input_section->output_section->vma + input_section->output_offset;
+
+ if (howto->pcrel_offset == true)
+ relocation -= reloc_entry->address;
+ }
+
+ if (output_bfd != (bfd *) NULL)
+ {
+ /* This is a partial relocation, and we want to apply the relocation
+ to the reloc entry rather than the raw data. Modify the reloc
+ inplace to reflect what we now know. */
+ reloc_entry->addend = relocation;
+ reloc_entry->address += input_section->output_offset;
+ return flag;
+ }
+ else
+ reloc_entry->addend = 0;
+
+ in1 = bfd_get_32 (abfd, (bfd_byte *) data + addr);
+ in2 = bfd_get_32 (abfd, (bfd_byte *) data + addr + 4);
+
+ printf("D30V 32-bit reloc at addr 0x%lx insn=0x%08x%08x\n",(long)relocation, (int)in1, (int)in2);
+ bfd_put_32 (abfd, in1, (bfd_byte *) data + addr);
+ bfd_put_32 (abfd, in2, (bfd_byte *) data + addr + 4);
+
+ return flag;
+}
+
+/* Map BFD reloc types to D30V ELF reloc types. */
+
+struct d30v_reloc_map
+{
+ unsigned char bfd_reloc_val;
+ unsigned char elf_reloc_val;
+};
+
+
+static const struct d30v_reloc_map d30v_reloc_map[] =
+{
+ { BFD_RELOC_NONE, R_D30V_NONE, },
+ { BFD_RELOC_D30V_6, R_D30V_6 },
+ { BFD_RELOC_D30V_15, R_D30V_15 },
+ { BFD_RELOC_D30V_15_PCREL, R_D30V_15_PCREL },
+ { BFD_RELOC_D30V_21, R_D30V_21 },
+ { BFD_RELOC_D30V_21_PCREL, R_D30V_21_PCREL },
+ { BFD_RELOC_D30V_32, R_D30V_32 },
+ { BFD_RELOC_D30V_32_PCREL, R_D30V_32_PCREL },
+ { BFD_RELOC_32, R_D30V_32_NORMAL },
+};
+
+static reloc_howto_type *
+bfd_elf32_bfd_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+ unsigned int i;
+
+ for (i = 0;
+ i < sizeof (d30v_reloc_map) / sizeof (struct d30v_reloc_map);
+ i++)
+ {
+ if (d30v_reloc_map[i].bfd_reloc_val == code)
+ return &elf_d30v_howto_table[d30v_reloc_map[i].elf_reloc_val];
+ }
+
+ return NULL;
+}
+
+/* Set the howto pointer for an D30V ELF reloc. */
+
+static void
+d30v_info_to_howto_rel (abfd, cache_ptr, dst)
+ bfd *abfd;
+ arelent *cache_ptr;
+ Elf32_Internal_Rel *dst;
+{
+ unsigned int r_type;
+
+ r_type = ELF32_R_TYPE (dst->r_info);
+ BFD_ASSERT (r_type < (unsigned int) R_D30V_max);
+ cache_ptr->howto = &elf_d30v_howto_table[r_type];
+}
+
+#define ELF_ARCH bfd_arch_d30v
+#define ELF_MACHINE_CODE EM_CYGNUS_D30V
+#define ELF_MAXPAGESIZE 0x1000
+
+#define TARGET_BIG_SYM bfd_elf32_d30v_vec
+#define TARGET_BIG_NAME "elf32-d30v"
+
+#define elf_info_to_howto 0
+#define elf_info_to_howto_rel d30v_info_to_howto_rel
+#define elf_backend_object_p 0
+#define elf_backend_final_write_processing 0
+
+#include "elf32-target.h"