/* M32R-specific support for 32-bit ELF.
- Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001
+ Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
bfd_byte *, bfd_vma));
bfd_reloc_status_type m32r_elf_lo16_reloc
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+bfd_reloc_status_type m32r_elf_generic_reloc
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
static bfd_reloc_status_type m32r_elf_sda16_reloc
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ m32r_elf_generic_reloc,/* special_function */
"R_M32R_16", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ m32r_elf_generic_reloc,/* special_function */
"R_M32R_32", /* name */
true, /* partial_inplace */
0xffffffff, /* src_mask */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_unsigned, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
+ m32r_elf_generic_reloc,/* special_function */
"R_M32R_24", /* name */
true, /* partial_inplace */
0xffffff, /* src_mask */
bfd *output_bfd;
char **error_message;
{
- bfd_reloc_status_type ret;
- bfd_vma relocation;
- unsigned long insn;
-
/* This part is from bfd_elf_generic_reloc.
If we're relocating, and this an external symbol, we don't want
to change anything. */
but we have partial_inplace == TRUE. bfd_elf_generic_reloc will
pass the handling back to bfd_install_relocation which will install
a section relative addend which is wrong. */
+ return m32r_elf_generic_reloc (input_bfd, reloc_entry, symbol, data,
+ input_section, output_bfd, error_message);
+}
+
+/* Do generic partial_inplace relocation.
+ This is a local replacement for bfd_elf_generic_reloc. */
+
+bfd_reloc_status_type
+m32r_elf_generic_reloc (input_bfd, reloc_entry, symbol, data,
+ input_section, output_bfd, error_message)
+ bfd *input_bfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message ATTRIBUTE_UNUSED;
+{
+ bfd_reloc_status_type ret;
+ bfd_vma relocation;
+ bfd_byte *inplace_address;
+
+ /* This part is from bfd_elf_generic_reloc.
+ If we're relocating, and this an external symbol, we don't want
+ to change anything. */
+ if (output_bfd != (bfd *) NULL
+ && (symbol->flags & BSF_SECTION_SYM) == 0
+ && reloc_entry->addend == 0)
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ /* Now do the the reloc in the usual way.
+ ??? It would be nice to call bfd_elf_generic_reloc here,
+ but we have partial_inplace == TRUE. bfd_elf_generic_reloc will
+ pass the handling back to bfd_install_relocation which will install
+ a section relative addend which is wrong. */
/* Sanity check the address (offset in section). */
if (reloc_entry->address > input_section->_cooked_size)
}
relocation += reloc_entry->addend;
+ inplace_address = (bfd_byte *) data + reloc_entry->address;
- insn = bfd_get_32 (input_bfd, data + reloc_entry->address);
- insn = (insn & 0xffff0000) | (relocation & 0xffff);
- bfd_put_32 (input_bfd, insn, data + reloc_entry->address);
+#define DOIT(x) \
+ x = ( (x & ~reloc_entry->howto->dst_mask) | \
+ (((x & reloc_entry->howto->src_mask) + relocation) & \
+ reloc_entry->howto->dst_mask))
+
+ switch (reloc_entry->howto->size)
+ {
+ case 1:
+ {
+ short x = bfd_get_16 (input_bfd, inplace_address);
+ DOIT (x);
+ bfd_put_16 (input_bfd, x, inplace_address);
+ }
+ break;
+ case 2:
+ {
+ unsigned long x = bfd_get_32 (input_bfd, inplace_address);
+ DOIT (x);
+ bfd_put_32 (input_bfd, x, inplace_address);
+ }
+ break;
+ default:
+ BFD_ASSERT (0);
+ }
if (output_bfd != (bfd *) NULL)
reloc_entry->address += input_section->output_offset;
When the chip supports parallel 16 bit insns, things may change.
*/
-static boolean
+static boolean
m32r_elf_relax_section (abfd, sec, link_info, again)
bfd *abfd;
asection *sec;
elf_elfheader (abfd)->e_flags |= val;
}
-/* Function to keep M32R specific file flags. */
+/* Function to keep M32R specific file flags. */
static boolean
m32r_elf_set_private_flags (abfd, flags)
bfd * abfd;
to the default values. */
if (bfd_get_arch_info (ibfd)->the_default)
return true;
-
+
elf_flags_init (obfd) = true;
elf_elfheader (obfd)->e_flags = in_flags;
PTR ptr;
{
FILE * file = (FILE *) ptr;
-
+
BFD_ASSERT (abfd != NULL && ptr != NULL)
-
+
_bfd_elf_print_private_bfd_data (abfd, ptr);
-
+
fprintf (file, _("private flags = %lx"), elf_elfheader (abfd)->e_flags);
-
+
switch (elf_elfheader (abfd)->e_flags & EF_M32R_ARCH)
{
default:
case E_M32R_ARCH: fprintf (file, _(": m32r instructions")); break;
case E_M32RX_ARCH: fprintf (file, _(": m32rx instructions")); break;
}
-
+
fputc ('\n', file);
-
+
return true;
}
case R_M32R_GNU_VTINHERIT:
case R_M32R_GNU_VTENTRY:
break;
-
+
default:
switch (h->root.type)
{
case bfd_link_hash_defined:
case bfd_link_hash_defweak:
return h->root.u.def.section;
-
+
case bfd_link_hash_common:
return h->root.u.c.p->section;
return true;
}
-
/* Look through the relocs for a section during the first phase.
Since we don't do .gots or .plts, we just need to consider the
virtual table relocs for gc. */
-
+
static boolean
m32r_elf_check_relocs (abfd, info, sec, relocs)
bfd *abfd;
struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
const Elf_Internal_Rela *rel;
const Elf_Internal_Rela *rel_end;
-
+
if (info->relocateable)
return true;
-
+
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
- sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf32_External_Sym);
+ sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
if (!elf_bad_symtab (abfd))
sym_hashes_end -= symtab_hdr->sh_info;
-
+
rel_end = relocs + sec->reloc_count;
for (rel = relocs; rel < rel_end; rel++)
{
struct elf_link_hash_entry *h;
unsigned long r_symndx;
-
+
r_symndx = ELF32_R_SYM (rel->r_info);
if (r_symndx < symtab_hdr->sh_info)
h = NULL;
else
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-
+
switch (ELF32_R_TYPE (rel->r_info))
{
/* This relocation describes the C++ object vtable hierarchy.
if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
return false;
break;
-
+
/* This relocation describes which C++ vtable entries are actually
used. Record for later use during GC. */
case R_M32R_GNU_VTENTRY:
break;
}
}
-
+
return true;
}
-
-
\f
-
#define ELF_ARCH bfd_arch_m32r
#define ELF_MACHINE_CODE EM_CYGNUS_M32R
#define ELF_MAXPAGESIZE 0x1 /* Explicitly requested by Mitsubishi. */
#define bfd_elf32_bfd_merge_private_bfd_data m32r_elf_merge_private_bfd_data
#define bfd_elf32_bfd_set_private_flags m32r_elf_set_private_flags
#define bfd_elf32_bfd_print_private_bfd_data m32r_elf_print_private_bfd_data
-
+
#include "elf32-target.h"