/* Morpho Technologies MT specific support for 32-bit ELF
- Copyright 2001, 2002, 2003, 2004, 2005, 2006
+ Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2011, 2012
Free Software Foundation, Inc.
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
+ 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,
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. */
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA. */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf/mt.h"
/* Prototypes. */
-static reloc_howto_type * mt_reloc_type_lookup
+static reloc_howto_type * mt_reloc_type_lookup
(bfd *, bfd_reloc_code_real_type);
static void mt_info_to_howto_rela
(bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma);
static bfd_reloc_status_type mt_final_link_relocate
- (reloc_howto_type *, bfd *, asection *, bfd_byte *,
+ (reloc_howto_type *, bfd *, asection *, bfd_byte *,
Elf_Internal_Rela *, bfd_vma);
static bfd_boolean mt_elf_relocate_section
- (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **);
/* Relocation tables. */
{
/* This reloc does nothing. */
HOWTO (R_MT_NONE, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
- FALSE, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MT_NONE", /* name */
- FALSE, /* partial_inplace */
- 0 , /* src_mask */
- 0, /* dst_mask */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MT_NONE", /* name */
+ FALSE, /* partial_inplace */
+ 0 , /* src_mask */
+ 0, /* dst_mask */
FALSE), /* pcrel_offset */
/* A 16 bit absolute relocation. */
HOWTO (R_MT_16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- FALSE, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MT_16", /* name */
- FALSE, /* partial_inplace */
- 0 , /* src_mask */
- 0xffff, /* dst_mask */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MT_16", /* name */
+ FALSE, /* partial_inplace */
+ 0 , /* src_mask */
+ 0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* A 32 bit absolute relocation. */
HOWTO (R_MT_32, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
- FALSE, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MT_32", /* name */
- FALSE, /* partial_inplace */
- 0 , /* src_mask */
- 0xffffffff, /* dst_mask */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MT_32", /* name */
+ FALSE, /* partial_inplace */
+ 0 , /* src_mask */
+ 0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
/* A 32 bit pc-relative relocation. */
HOWTO (R_MT_32_PCREL, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
- TRUE, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_dont, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MT_32_PCREL", /* name */
- FALSE, /* partial_inplace */
- 0 , /* src_mask */
- 0xffffffff, /* dst_mask */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MT_32_PCREL", /* name */
+ FALSE, /* partial_inplace */
+ 0 , /* src_mask */
+ 0xffffffff, /* dst_mask */
TRUE), /* pcrel_offset */
/* A 16 bit pc-relative relocation. */
HOWTO (R_MT_PC16, /* type */
- 0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
- TRUE, /* pc_relative */
- 0, /* bitpos */
- complain_overflow_signed, /* complain_on_overflow */
- bfd_elf_generic_reloc, /* special_function */
- "R_MT_PC16", /* name */
- FALSE, /* partial_inplace */
- 0, /* src_mask */
- 0xffff, /* dst_mask */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MT_PC16", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
TRUE), /* pcrel_offset */
/* high 16 bits of symbol value. */
return NULL;
}
+static reloc_howto_type *
+mt_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *r_name)
+{
+ unsigned int i;
+
+ for (i = 0;
+ i < sizeof (mt_elf_howto_table) / sizeof (mt_elf_howto_table[0]);
+ i++)
+ if (mt_elf_howto_table[i].name != NULL
+ && strcasecmp (mt_elf_howto_table[i].name, r_name) == 0)
+ return &mt_elf_howto_table[i];
+
+ return NULL;
+}
+
bfd_reloc_status_type
mt_elf_relocate_hi16
(bfd * input_bfd,
bfd_reloc_status_type r;
const char * name = NULL;
int r_type;
-
+
r_type = ELF32_R_TYPE (rel->r_info);
r_symndx = ELF32_R_SYM (rel->r_info);
- /* This is a final link. */
howto = mt_elf_howto_table + ELF32_R_TYPE (rel->r_info);
h = NULL;
sym = NULL;
sec = NULL;
-
+
if (r_symndx < symtab_hdr->sh_info)
{
sym = local_syms + r_symndx;
sec = local_sections [r_symndx];
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
-
+
name = bfd_elf_string_from_elf_section
(input_bfd, symtab_hdr->sh_link, sym->st_name);
name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
else
{
bfd_boolean unresolved_reloc;
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
name = h->root.root.string;
}
+ if (sec != NULL && discarded_section (sec))
+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+ rel, 1, relend, howto, 0, contents);
+
+ if (info->relocatable)
+ continue;
/* Finally, the sole MT-specific part. */
switch (r_type)
(info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0,
input_bfd, input_section, rel->r_offset);
break;
-
+
case bfd_reloc_undefined:
r = info->callbacks->undefined_symbol
(info, name, input_bfd, input_section, rel->r_offset, TRUE);
break;
-
+
case bfd_reloc_outofrange:
msg = _("internal error: out of range error");
break;
/* 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 bfd_boolean
mt_elf_check_relocs
(bfd * abfd,
{
Elf_Internal_Shdr * symtab_hdr;
struct elf_link_hash_entry ** sym_hashes;
- struct elf_link_hash_entry ** sym_hashes_end;
const Elf_Internal_Rela * rel;
const Elf_Internal_Rela * rel_end;
-
+
if (info->relocatable)
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);
- 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;
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ /* PR15323, ref flags aren't set for references in the same
+ object. */
+ h->root.non_ir_ref = 1;
}
}
return TRUE;
}
-static bfd_boolean
-mt_elf_copy_private_bfd_data (bfd * ibfd, bfd * obfd)
-{
- if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
- || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return TRUE;
-
- BFD_ASSERT (!elf_flags_init (obfd)
- || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
-
- elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
- elf_flags_init (obfd) = TRUE;
- return TRUE;
-}
-
/* Merge backend specific data from an object file to the output
object file when linking. */
flagword old_flags, new_flags;
bfd_boolean ok = TRUE;
- /* Check if we have the same endianess. */
+ /* Check if we have the same endianness. */
if (_bfd_generic_verify_endian_match (ibfd, obfd) == FALSE)
return FALSE;
MS2 are not subsets of each other. */
ok = FALSE;
}
-
+
if (ok)
{
obfd->arch_info = ibfd->arch_info;
flagword flags;
BFD_ASSERT (abfd != NULL && ptr != NULL);
-
+
/* Print normal ELF private data. */
_bfd_elf_print_private_bfd_data (abfd, ptr);
flags = elf_elfheader (abfd)->e_flags;
- fprintf (file, _("private flags = 0x%lx:"), (long)flags);
+ fprintf (file, _("private flags = 0x%lx:"), (unsigned long) flags);
switch (flags & EF_MT_CPU_MASK)
{
#define elf_backend_relocate_section mt_elf_relocate_section
#define bfd_elf32_bfd_reloc_type_lookup mt_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_name_lookup mt_reloc_name_lookup
#define elf_backend_check_relocs mt_elf_check_relocs
#define elf_backend_object_p mt_elf_object_p
#define elf_backend_can_gc_sections 1
#define bfd_elf32_bfd_set_private_flags mt_elf_set_private_flags
-#define bfd_elf32_bfd_copy_private_bfd_data mt_elf_copy_private_bfd_data
#define bfd_elf32_bfd_merge_private_bfd_data mt_elf_merge_private_bfd_data
#define bfd_elf32_bfd_print_private_bfd_data mt_elf_print_private_bfd_data