/* Matsushita 10300 specific support for 32-bit ELF
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 1996-2017 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
/* Calculated value. */
bfd_vma value;
+
+#define GOT_UNKNOWN 0
+#define GOT_NORMAL 1
+#define GOT_TLS_GD 2
+#define GOT_TLS_LD 3
+#define GOT_TLS_IE 4
+ /* Used to distinguish GOT entries for TLS types from normal GOT entries. */
+ unsigned char tls_type;
};
/* We derive a hash table from the main elf linker hash table so
/* Random linker state flags. */
#define MN10300_HASH_ENTRIES_INITIALIZED 0x1
char flags;
+ struct
+ {
+ bfd_signed_vma refcount;
+ bfd_vma offset;
+ char got_allocated;
+ char rel_emitted;
+ } tls_ldm_got;
+};
+
+#define elf_mn10300_hash_entry(ent) ((struct elf32_mn10300_link_hash_entry *)(ent))
+
+struct elf_mn10300_obj_tdata
+{
+ struct elf_obj_tdata root;
+
+ /* tls_type for each local got entry. */
+ char * local_got_tls_type;
};
+#define elf_mn10300_tdata(abfd) \
+ ((struct elf_mn10300_obj_tdata *) (abfd)->tdata.any)
+
+#define elf_mn10300_local_got_tls_type(abfd) \
+ (elf_mn10300_tdata (abfd)->local_got_tls_type)
+
#ifndef streq
#define streq(a, b) (strcmp ((a),(b)) == 0)
#endif
/* Dummy relocation. Does nothing. */
HOWTO (R_MN10300_NONE,
0,
- 2,
- 16,
+ 3,
+ 0,
FALSE,
0,
- complain_overflow_bitfield,
+ complain_overflow_dont,
bfd_elf_generic_reloc,
"R_MN10300_NONE",
FALSE,
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
- EMPTY_HOWTO (24),
- EMPTY_HOWTO (25),
- EMPTY_HOWTO (26),
- EMPTY_HOWTO (27),
- EMPTY_HOWTO (28),
- EMPTY_HOWTO (29),
- EMPTY_HOWTO (30),
- EMPTY_HOWTO (31),
- EMPTY_HOWTO (32),
-
+ HOWTO (R_MN10300_TLS_GD, /* 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, /* */
+ "R_MN10300_TLS_GD", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_MN10300_TLS_LD, /* 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, /* */
+ "R_MN10300_TLS_LD", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_MN10300_TLS_LDO, /* 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, /* */
+ "R_MN10300_TLS_LDO", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_MN10300_TLS_GOTIE, /* 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, /* */
+ "R_MN10300_TLS_GOTIE", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_MN10300_TLS_IE, /* 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, /* */
+ "R_MN10300_TLS_IE", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_MN10300_TLS_LE, /* 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, /* */
+ "R_MN10300_TLS_LE", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_MN10300_TLS_DTPMOD, /* 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, /* */
+ "R_MN10300_TLS_DTPMOD", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_MN10300_TLS_DTPOFF, /* 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, /* */
+ "R_MN10300_TLS_DTPOFF", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_MN10300_TLS_TPOFF, /* 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, /* */
+ "R_MN10300_TLS_TPOFF", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
HOWTO (R_MN10300_SYM_DIFF, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
{ BFD_RELOC_MN10300_GLOB_DAT, R_MN10300_GLOB_DAT },
{ BFD_RELOC_MN10300_JMP_SLOT, R_MN10300_JMP_SLOT },
{ BFD_RELOC_MN10300_RELATIVE, R_MN10300_RELATIVE },
+ { BFD_RELOC_MN10300_TLS_GD, R_MN10300_TLS_GD },
+ { BFD_RELOC_MN10300_TLS_LD, R_MN10300_TLS_LD },
+ { BFD_RELOC_MN10300_TLS_LDO, R_MN10300_TLS_LDO },
+ { BFD_RELOC_MN10300_TLS_GOTIE, R_MN10300_TLS_GOTIE },
+ { BFD_RELOC_MN10300_TLS_IE, R_MN10300_TLS_IE },
+ { BFD_RELOC_MN10300_TLS_LE, R_MN10300_TLS_LE },
+ { BFD_RELOC_MN10300_TLS_DTPMOD, R_MN10300_TLS_DTPMOD },
+ { BFD_RELOC_MN10300_TLS_DTPOFF, R_MN10300_TLS_DTPOFF },
+ { BFD_RELOC_MN10300_TLS_TPOFF, R_MN10300_TLS_TPOFF },
{ BFD_RELOC_MN10300_SYM_DIFF, R_MN10300_SYM_DIFF },
{ BFD_RELOC_MN10300_ALIGN, R_MN10300_ALIGN }
};
asection * s;
struct elf_link_hash_entry * h;
const struct elf_backend_data * bed = get_elf_backend_data (abfd);
+ struct elf_link_hash_table *htab;
int ptralign;
/* This function may be called more than once. */
- if (bfd_get_section_by_name (abfd, ".got") != NULL)
+ htab = elf_hash_table (info);
+ if (htab->sgot != NULL)
return TRUE;
switch (bed->s->arch_size)
if (bed->plt_readonly)
pltflags |= SEC_READONLY;
- s = bfd_make_section_with_flags (abfd, ".plt", pltflags);
+ s = bfd_make_section_anyway_with_flags (abfd, ".plt", pltflags);
+ htab->splt = s;
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
return FALSE;
{
h = _bfd_elf_define_linkage_sym (abfd, info, s,
"_PROCEDURE_LINKAGE_TABLE_");
- elf_hash_table (info)->hplt = h;
+ htab->hplt = h;
if (h == NULL)
return FALSE;
}
- s = bfd_make_section_with_flags (abfd, ".got", flags);
+ s = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
+ htab->sgot = s;
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, ptralign))
return FALSE;
if (bed->want_got_plt)
{
- s = bfd_make_section_with_flags (abfd, ".got.plt", flags);
+ s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
+ htab->sgotplt = s;
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, ptralign))
return FALSE;
because we don't want to define the symbol if we are not creating
a global offset table. */
h = _bfd_elf_define_linkage_sym (abfd, info, s, "_GLOBAL_OFFSET_TABLE_");
- elf_hash_table (info)->hgot = h;
+ htab->hgot = h;
if (h == NULL)
return FALSE;
unsigned int r_type;
r_type = ELF32_R_TYPE (dst->r_info);
- BFD_ASSERT (r_type < (unsigned int) R_MN10300_MAX);
+ if (r_type >= R_MN10300_MAX)
+ {
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B: unrecognised MN10300 reloc number: %d"),
+ abfd, r_type);
+ bfd_set_error (bfd_error_bad_value);
+ r_type = R_MN10300_NONE;
+ }
cache_ptr->howto = elf_mn10300_howto_table + r_type;
}
+static int
+elf_mn10300_tls_transition (struct bfd_link_info * info,
+ int r_type,
+ struct elf_link_hash_entry * h,
+ asection * sec,
+ bfd_boolean counting)
+{
+ bfd_boolean is_local;
+
+ if (r_type == R_MN10300_TLS_GD
+ && h != NULL
+ && elf_mn10300_hash_entry (h)->tls_type == GOT_TLS_IE)
+ return R_MN10300_TLS_GOTIE;
+
+ if (bfd_link_pic (info))
+ return r_type;
+
+ if (! (sec->flags & SEC_CODE))
+ return r_type;
+
+ if (! counting && h != NULL && ! elf_hash_table (info)->dynamic_sections_created)
+ is_local = TRUE;
+ else
+ is_local = SYMBOL_CALLS_LOCAL (info, h);
+
+ /* For the main program, these are the transitions we do. */
+ switch (r_type)
+ {
+ case R_MN10300_TLS_GD: return is_local ? R_MN10300_TLS_LE : R_MN10300_TLS_GOTIE;
+ case R_MN10300_TLS_LD: return R_MN10300_NONE;
+ case R_MN10300_TLS_LDO: return R_MN10300_TLS_LE;
+ case R_MN10300_TLS_IE:
+ case R_MN10300_TLS_GOTIE: return is_local ? R_MN10300_TLS_LE : r_type;
+ }
+
+ return r_type;
+}
+
+/* Return the relocation value for @tpoff relocation
+ if STT_TLS virtual address is ADDRESS. */
+
+static bfd_vma
+dtpoff (struct bfd_link_info * info, bfd_vma address)
+{
+ struct elf_link_hash_table *htab = elf_hash_table (info);
+
+ /* If tls_sec is NULL, we should have signalled an error already. */
+ if (htab->tls_sec == NULL)
+ return 0;
+ return address - htab->tls_sec->vma;
+}
+
+/* Return the relocation value for @tpoff relocation
+ if STT_TLS virtual address is ADDRESS. */
+
+static bfd_vma
+tpoff (struct bfd_link_info * info, bfd_vma address)
+{
+ struct elf_link_hash_table *htab = elf_hash_table (info);
+
+ /* If tls_sec is NULL, we should have signalled an error already. */
+ if (htab->tls_sec == NULL)
+ return 0;
+ return address - (htab->tls_size + htab->tls_sec->vma);
+}
+
+/* Returns nonzero if there's a R_MN10300_PLT32 reloc that we now need
+ to skip, after this one. The actual value is the offset between
+ this reloc and the PLT reloc. */
+
+static int
+mn10300_do_tls_transition (bfd * input_bfd,
+ unsigned int r_type,
+ unsigned int tls_r_type,
+ bfd_byte * contents,
+ bfd_vma offset)
+{
+ bfd_byte *op = contents + offset;
+ int gotreg = 0;
+
+#define TLS_PAIR(r1,r2) ((r1) * R_MN10300_MAX + (r2))
+
+ /* This is common to all GD/LD transitions, so break it out. */
+ if (r_type == R_MN10300_TLS_GD
+ || r_type == R_MN10300_TLS_LD)
+ {
+ op -= 2;
+ /* mov imm,d0. */
+ BFD_ASSERT (bfd_get_8 (input_bfd, op) == 0xFC);
+ BFD_ASSERT (bfd_get_8 (input_bfd, op + 1) == 0xCC);
+ /* add aN,d0. */
+ BFD_ASSERT (bfd_get_8 (input_bfd, op + 6) == 0xF1);
+ gotreg = (bfd_get_8 (input_bfd, op + 7) & 0x0c) >> 2;
+ /* Call. */
+ BFD_ASSERT (bfd_get_8 (input_bfd, op + 8) == 0xDD);
+ }
+
+ switch (TLS_PAIR (r_type, tls_r_type))
+ {
+ case TLS_PAIR (R_MN10300_TLS_GD, R_MN10300_TLS_GOTIE):
+ {
+ /* Keep track of which register we put GOTptr in. */
+ /* mov (_x@indntpoff,a2),a0. */
+ memcpy (op, "\xFC\x20\x00\x00\x00\x00", 6);
+ op[1] |= gotreg;
+ /* add e2,a0. */
+ memcpy (op+6, "\xF9\x78\x28", 3);
+ /* or 0x00000000, d0 - six byte nop. */
+ memcpy (op+9, "\xFC\xE4\x00\x00\x00\x00", 6);
+ }
+ return 7;
+
+ case TLS_PAIR (R_MN10300_TLS_GD, R_MN10300_TLS_LE):
+ {
+ /* Register is *always* a0. */
+ /* mov _x@tpoff,a0. */
+ memcpy (op, "\xFC\xDC\x00\x00\x00\x00", 6);
+ /* add e2,a0. */
+ memcpy (op+6, "\xF9\x78\x28", 3);
+ /* or 0x00000000, d0 - six byte nop. */
+ memcpy (op+9, "\xFC\xE4\x00\x00\x00\x00", 6);
+ }
+ return 7;
+ case TLS_PAIR (R_MN10300_TLS_LD, R_MN10300_NONE):
+ {
+ /* Register is *always* a0. */
+ /* mov e2,a0. */
+ memcpy (op, "\xF5\x88", 2);
+ /* or 0x00000000, d0 - six byte nop. */
+ memcpy (op+2, "\xFC\xE4\x00\x00\x00\x00", 6);
+ /* or 0x00000000, e2 - seven byte nop. */
+ memcpy (op+8, "\xFE\x19\x22\x00\x00\x00\x00", 7);
+ }
+ return 7;
+
+ case TLS_PAIR (R_MN10300_TLS_LDO, R_MN10300_TLS_LE):
+ /* No changes needed, just the reloc change. */
+ return 0;
+
+ /* These are a little tricky, because we have to detect which
+ opcode is being used (they're different sizes, with the reloc
+ at different offsets within the opcode) and convert each
+ accordingly, copying the operands as needed. The conversions
+ we do are as follows (IE,GOTIE,LE):
+
+ 1111 1100 1010 01Dn [-- abs32 --] MOV (x@indntpoff),Dn
+ 1111 1100 0000 DnAm [-- abs32 --] MOV (x@gotntpoff,Am),Dn
+ 1111 1100 1100 11Dn [-- abs32 --] MOV x@tpoff,Dn
+
+ 1111 1100 1010 00An [-- abs32 --] MOV (x@indntpoff),An
+ 1111 1100 0010 AnAm [-- abs32 --] MOV (x@gotntpoff,Am),An
+ 1111 1100 1101 11An [-- abs32 --] MOV x@tpoff,An
+
+ 1111 1110 0000 1110 Rnnn Xxxx [-- abs32 --] MOV (x@indntpoff),Rn
+ 1111 1110 0000 1010 Rnnn Rmmm [-- abs32 --] MOV (x@indntpoff,Rm),Rn
+ 1111 1110 0000 1000 Rnnn Xxxx [-- abs32 --] MOV x@tpoff,Rn
+
+ Since the GOT pointer is always $a2, we assume the last
+ normally won't happen, but let's be paranoid and plan for the
+ day that GCC optimizes it somewhow. */
+
+ case TLS_PAIR (R_MN10300_TLS_IE, R_MN10300_TLS_LE):
+ if (op[-2] == 0xFC)
+ {
+ op -= 2;
+ if ((op[1] & 0xFC) == 0xA4) /* Dn */
+ {
+ op[1] &= 0x03; /* Leaves Dn. */
+ op[1] |= 0xCC;
+ }
+ else /* An */
+ {
+ op[1] &= 0x03; /* Leaves An. */
+ op[1] |= 0xDC;
+ }
+ }
+ else if (op[-3] == 0xFE)
+ op[-2] = 0x08;
+ else
+ abort ();
+ break;
+
+ case TLS_PAIR (R_MN10300_TLS_GOTIE, R_MN10300_TLS_LE):
+ if (op[-2] == 0xFC)
+ {
+ op -= 2;
+ if ((op[1] & 0xF0) == 0x00) /* Dn */
+ {
+ op[1] &= 0x0C; /* Leaves Dn. */
+ op[1] >>= 2;
+ op[1] |= 0xCC;
+ }
+ else /* An */
+ {
+ op[1] &= 0x0C; /* Leaves An. */
+ op[1] >>= 2;
+ op[1] |= 0xDC;
+ }
+ }
+ else if (op[-3] == 0xFE)
+ op[-2] = 0x08;
+ else
+ abort ();
+ break;
+
+ default:
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: Unsupported transition from %s to %s"),
+ input_bfd,
+ elf_mn10300_howto_table[r_type].name,
+ elf_mn10300_howto_table[tls_r_type].name);
+ break;
+ }
+#undef TLS_PAIR
+ return 0;
+}
+
/* 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. */
asection *sec,
const Elf_Internal_Rela *relocs)
{
+ struct elf32_mn10300_link_hash_table * htab = elf32_mn10300_hash_table (info);
bfd_boolean sym_diff_reloc_seen;
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Sym * isymbuf = NULL;
srelgot = NULL;
sreloc = NULL;
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
return TRUE;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
struct elf_link_hash_entry *h;
unsigned long r_symndx;
unsigned int r_type;
+ int tls_type = GOT_NORMAL;
r_symndx = ELF32_R_SYM (rel->r_info);
if (r_symndx < symtab_hdr->sh_info)
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;
}
r_type = ELF32_R_TYPE (rel->r_info);
+ r_type = elf_mn10300_tls_transition (info, r_type, h, sec, TRUE);
/* Some relocs require a global offset table. */
if (dynobj == NULL)
case R_MN10300_GOTOFF16:
case R_MN10300_GOTPC32:
case R_MN10300_GOTPC16:
+ case R_MN10300_TLS_GD:
+ case R_MN10300_TLS_LD:
+ case R_MN10300_TLS_GOTIE:
+ case R_MN10300_TLS_IE:
elf_hash_table (info)->dynobj = dynobj = abfd;
if (! _bfd_mn10300_elf_create_got_section (dynobj, info))
goto fail;
goto fail;
break;
+ case R_MN10300_TLS_LD:
+ htab->tls_ldm_got.refcount ++;
+ tls_type = GOT_TLS_LD;
+
+ if (htab->tls_ldm_got.got_allocated)
+ break;
+ goto create_got;
+
+ case R_MN10300_TLS_IE:
+ case R_MN10300_TLS_GOTIE:
+ if (bfd_link_pic (info))
+ info->flags |= DF_STATIC_TLS;
+ /* Fall through */
+
+ case R_MN10300_TLS_GD:
case R_MN10300_GOT32:
case R_MN10300_GOT24:
case R_MN10300_GOT16:
+ create_got:
/* This symbol requires a global offset table entry. */
- if (sgot == NULL)
+ switch (r_type)
{
- sgot = bfd_get_section_by_name (dynobj, ".got");
- BFD_ASSERT (sgot != NULL);
+ case R_MN10300_TLS_IE:
+ case R_MN10300_TLS_GOTIE: tls_type = GOT_TLS_IE; break;
+ case R_MN10300_TLS_GD: tls_type = GOT_TLS_GD; break;
+ default: tls_type = GOT_NORMAL; break;
}
- if (srelgot == NULL
- && (h != NULL || info->shared))
+ sgot = htab->root.sgot;
+ srelgot = htab->root.srelgot;
+ BFD_ASSERT (sgot != NULL && srelgot != NULL);
+
+ if (r_type == R_MN10300_TLS_LD)
+ {
+ htab->tls_ldm_got.offset = sgot->size;
+ htab->tls_ldm_got.got_allocated ++;
+ }
+ else if (h != NULL)
{
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
- if (srelgot == NULL)
+ if (elf_mn10300_hash_entry (h)->tls_type != tls_type
+ && elf_mn10300_hash_entry (h)->tls_type != GOT_UNKNOWN)
{
- srelgot = bfd_make_section_with_flags (dynobj,
- ".rela.got",
- (SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED
- | SEC_READONLY));
- if (srelgot == NULL
- || ! bfd_set_section_alignment (dynobj, srelgot, 2))
- goto fail;
+ if (tls_type == GOT_TLS_IE
+ && elf_mn10300_hash_entry (h)->tls_type == GOT_TLS_GD)
+ /* No change - this is ok. */;
+ else if (tls_type == GOT_TLS_GD
+ && elf_mn10300_hash_entry (h)->tls_type == GOT_TLS_IE)
+ /* Transition GD->IE. */
+ tls_type = GOT_TLS_IE;
+ else
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B: %s' accessed both as normal and thread local symbol"),
+ abfd, h ? h->root.root.string : "<local>");
}
- }
- if (h != NULL)
- {
+ elf_mn10300_hash_entry (h)->tls_type = tls_type;
+
if (h->got.offset != (bfd_vma) -1)
/* We have already allocated space in the .got. */
break;
h->got.offset = sgot->size;
- /* Make sure this symbol is output as a dynamic symbol. */
- if (h->dynindx == -1)
+ if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL
+ /* Make sure this symbol is output as a dynamic symbol. */
+ && h->dynindx == -1)
{
if (! bfd_elf_link_record_dynamic_symbol (info, h))
goto fail;
}
srelgot->size += sizeof (Elf32_External_Rela);
+ if (r_type == R_MN10300_TLS_GD)
+ srelgot->size += sizeof (Elf32_External_Rela);
}
else
{
size_t size;
unsigned int i;
- size = symtab_hdr->sh_info * sizeof (bfd_vma);
+ size = symtab_hdr->sh_info * (sizeof (bfd_vma) + sizeof (char));
local_got_offsets = bfd_alloc (abfd, size);
if (local_got_offsets == NULL)
goto fail;
elf_local_got_offsets (abfd) = local_got_offsets;
+ elf_mn10300_local_got_tls_type (abfd)
+ = (char *) (local_got_offsets + symtab_hdr->sh_info);
for (i = 0; i < symtab_hdr->sh_info; i++)
local_got_offsets[i] = (bfd_vma) -1;
local_got_offsets[r_symndx] = sgot->size;
- if (info->shared)
- /* If we are generating a shared object, we need to
- output a R_MN10300_RELATIVE reloc so that the dynamic
- linker can adjust this GOT entry. */
- srelgot->size += sizeof (Elf32_External_Rela);
+ if (bfd_link_pic (info))
+ {
+ /* If we are generating a shared object, we need to
+ output a R_MN10300_RELATIVE reloc so that the dynamic
+ linker can adjust this GOT entry. */
+ srelgot->size += sizeof (Elf32_External_Rela);
+
+ if (r_type == R_MN10300_TLS_GD)
+ /* And a R_MN10300_TLS_DTPOFF reloc as well. */
+ srelgot->size += sizeof (Elf32_External_Rela);
+ }
+
+ elf_mn10300_local_got_tls_type (abfd) [r_symndx] = tls_type;
}
sgot->size += 4;
- break;
+ if (r_type == R_MN10300_TLS_GD
+ || r_type == R_MN10300_TLS_LD)
+ sgot->size += 4;
+
+ goto need_shared_relocs;
case R_MN10300_PLT32:
case R_MN10300_PLT16:
if (h != NULL)
h->non_got_ref = 1;
+ need_shared_relocs:
/* If we are creating a shared library, then we
need to copy the reloc into the shared library. */
- if (info->shared
+ if (bfd_link_pic (info)
&& (sec->flags & SEC_ALLOC) != 0
/* Do not generate a dynamic reloc for a
reloc associated with a SYM_DIFF operation. */
asection *sym_sec ATTRIBUTE_UNUSED,
int is_local ATTRIBUTE_UNUSED)
{
+ struct elf32_mn10300_link_hash_table * htab = elf32_mn10300_hash_table (info);
static asection * sym_diff_section;
static bfd_vma sym_diff_value;
bfd_boolean is_sym_diff_reloc;
case R_MN10300_GOTOFF32:
case R_MN10300_GOTOFF24:
case R_MN10300_GOTOFF16:
- if (info->shared
+ if (bfd_link_pic (info)
+ && (input_section->flags & SEC_ALLOC) != 0
+ && h != NULL
+ && ! SYMBOL_REFERENCES_LOCAL (info, h))
+ return bfd_reloc_dangerous;
+ /* Fall through. */
+ case R_MN10300_GOT32:
+ /* Issue 2052223:
+ Taking the address of a protected function in a shared library
+ is illegal. Issue an error message here. */
+ if (bfd_link_pic (info)
&& (input_section->flags & SEC_ALLOC) != 0
&& h != NULL
+ && ELF_ST_VISIBILITY (h->other) == STV_PROTECTED
+ && (h->type == STT_FUNC || h->type == STT_GNU_IFUNC)
&& ! SYMBOL_REFERENCES_LOCAL (info, h))
return bfd_reloc_dangerous;
}
return bfd_reloc_ok;
case R_MN10300_32:
- if (info->shared
+ if (bfd_link_pic (info)
/* Do not generate relocs when an R_MN10300_32 has been used
with an R_MN10300_SYM_DIFF to compute a difference of two
symbols. */
return bfd_reloc_ok;
case R_MN10300_GOTPC32:
+ if (dynobj == NULL)
+ return bfd_reloc_dangerous;
+
/* Use global offset table as symbol value. */
- value = bfd_get_section_by_name (dynobj,
- ".got")->output_section->vma;
+ value = htab->root.sgot->output_section->vma;
value -= (input_section->output_section->vma
+ input_section->output_offset);
value -= offset;
return bfd_reloc_ok;
case R_MN10300_GOTPC16:
+ if (dynobj == NULL)
+ return bfd_reloc_dangerous;
+
/* Use global offset table as symbol value. */
- value = bfd_get_section_by_name (dynobj,
- ".got")->output_section->vma;
+ value = htab->root.sgot->output_section->vma;
value -= (input_section->output_section->vma
+ input_section->output_offset);
value -= offset;
return bfd_reloc_ok;
case R_MN10300_GOTOFF32:
- value -= bfd_get_section_by_name (dynobj,
- ".got")->output_section->vma;
+ if (dynobj == NULL)
+ return bfd_reloc_dangerous;
+
+ value -= htab->root.sgot->output_section->vma;
value += addend;
bfd_put_32 (input_bfd, value, hit_data);
return bfd_reloc_ok;
case R_MN10300_GOTOFF24:
- value -= bfd_get_section_by_name (dynobj,
- ".got")->output_section->vma;
+ if (dynobj == NULL)
+ return bfd_reloc_dangerous;
+
+ value -= htab->root.sgot->output_section->vma;
value += addend;
if ((long) value > 0x7fffff || (long) value < -0x800000)
return bfd_reloc_ok;
case R_MN10300_GOTOFF16:
- value -= bfd_get_section_by_name (dynobj,
- ".got")->output_section->vma;
+ if (dynobj == NULL)
+ return bfd_reloc_dangerous;
+
+ value -= htab->root.sgot->output_section->vma;
value += addend;
if ((long) value > 0x7fff || (long) value < -0x8000)
&& ELF_ST_VISIBILITY (h->other) != STV_HIDDEN
&& h->plt.offset != (bfd_vma) -1)
{
- splt = bfd_get_section_by_name (dynobj, ".plt");
+ if (dynobj == NULL)
+ return bfd_reloc_dangerous;
+ splt = htab->root.splt;
value = (splt->output_section->vma
+ splt->output_offset
+ h->plt.offset) - value;
&& ELF_ST_VISIBILITY (h->other) != STV_HIDDEN
&& h->plt.offset != (bfd_vma) -1)
{
- splt = bfd_get_section_by_name (dynobj, ".plt");
+ if (dynobj == NULL)
+ return bfd_reloc_dangerous;
+ splt = htab->root.splt;
value = (splt->output_section->vma
+ splt->output_offset
+ h->plt.offset) - value;
bfd_put_16 (input_bfd, value, hit_data);
return bfd_reloc_ok;
+ case R_MN10300_TLS_LDO:
+ value = dtpoff (info, value);
+ bfd_put_32 (input_bfd, value + addend, hit_data);
+ return bfd_reloc_ok;
+
+ case R_MN10300_TLS_LE:
+ value = tpoff (info, value);
+ bfd_put_32 (input_bfd, value + addend, hit_data);
+ return bfd_reloc_ok;
+
+ case R_MN10300_TLS_LD:
+ if (dynobj == NULL)
+ return bfd_reloc_dangerous;
+
+ sgot = htab->root.sgot;
+ BFD_ASSERT (sgot != NULL);
+ value = htab->tls_ldm_got.offset + sgot->output_offset;
+ bfd_put_32 (input_bfd, value, hit_data);
+
+ if (!htab->tls_ldm_got.rel_emitted)
+ {
+ asection *srelgot = htab->root.srelgot;
+ Elf_Internal_Rela rel;
+
+ BFD_ASSERT (srelgot != NULL);
+ htab->tls_ldm_got.rel_emitted ++;
+ rel.r_offset = (sgot->output_section->vma
+ + sgot->output_offset
+ + htab->tls_ldm_got.offset);
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + htab->tls_ldm_got.offset);
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + htab->tls_ldm_got.offset+4);
+ rel.r_info = ELF32_R_INFO (0, R_MN10300_TLS_DTPMOD);
+ rel.r_addend = 0;
+ bfd_elf32_swap_reloca_out (output_bfd, & rel,
+ (bfd_byte *) ((Elf32_External_Rela *) srelgot->contents
+ + srelgot->reloc_count));
+ ++ srelgot->reloc_count;
+ }
+
+ return bfd_reloc_ok;
+
+ case R_MN10300_TLS_GOTIE:
+ value = tpoff (info, value);
+ /* Fall Through. */
+
+ case R_MN10300_TLS_GD:
+ case R_MN10300_TLS_IE:
case R_MN10300_GOT32:
case R_MN10300_GOT24:
case R_MN10300_GOT16:
- {
- sgot = bfd_get_section_by_name (dynobj, ".got");
+ if (dynobj == NULL)
+ return bfd_reloc_dangerous;
- if (h != NULL)
- {
- bfd_vma off;
+ sgot = htab->root.sgot;
+ if (r_type == R_MN10300_TLS_GD)
+ value = dtpoff (info, value);
- off = h->got.offset;
- BFD_ASSERT (off != (bfd_vma) -1);
+ if (h != NULL)
+ {
+ bfd_vma off;
+
+ off = h->got.offset;
+ /* Offsets in the GOT are allocated in check_relocs
+ which is not called for shared libraries... */
+ if (off == (bfd_vma) -1)
+ off = 0;
+
+ if (sgot->contents != NULL
+ && (! elf_hash_table (info)->dynamic_sections_created
+ || SYMBOL_REFERENCES_LOCAL (info, h)))
+ /* This is actually a static link, or it is a
+ -Bsymbolic link and the symbol is defined
+ locally, or the symbol was forced to be local
+ because of a version file. We must initialize
+ this entry in the global offset table.
+
+ When doing a dynamic link, we create a .rela.got
+ relocation entry to initialize the value. This
+ is done in the finish_dynamic_symbol routine. */
+ bfd_put_32 (output_bfd, value,
+ sgot->contents + off);
+
+ value = sgot->output_offset + off;
+ }
+ else
+ {
+ bfd_vma off;
- if (! elf_hash_table (info)->dynamic_sections_created
- || SYMBOL_REFERENCES_LOCAL (info, h))
- /* This is actually a static link, or it is a
- -Bsymbolic link and the symbol is defined
- locally, or the symbol was forced to be local
- because of a version file. We must initialize
- this entry in the global offset table.
-
- When doing a dynamic link, we create a .rela.got
- relocation entry to initialize the value. This
- is done in the finish_dynamic_symbol routine. */
- bfd_put_32 (output_bfd, value,
- sgot->contents + off);
-
- value = sgot->output_offset + off;
- }
+ off = elf_local_got_offsets (input_bfd)[symndx];
+
+ if (off & 1)
+ bfd_put_32 (output_bfd, value, sgot->contents + (off & ~ 1));
else
{
- bfd_vma off;
-
- off = elf_local_got_offsets (input_bfd)[symndx];
-
bfd_put_32 (output_bfd, value, sgot->contents + off);
- if (info->shared)
+ if (bfd_link_pic (info))
{
- asection * srelgot;
+ asection *srelgot = htab->root.srelgot;;
Elf_Internal_Rela outrel;
- srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
BFD_ASSERT (srelgot != NULL);
outrel.r_offset = (sgot->output_section->vma
+ sgot->output_offset
+ off);
- outrel.r_info = ELF32_R_INFO (0, R_MN10300_RELATIVE);
+ switch (r_type)
+ {
+ case R_MN10300_TLS_GD:
+ outrel.r_info = ELF32_R_INFO (0, R_MN10300_TLS_DTPOFF);
+ outrel.r_offset = (sgot->output_section->vma
+ + sgot->output_offset
+ + off + 4);
+ bfd_elf32_swap_reloca_out (output_bfd, & outrel,
+ (bfd_byte *) (((Elf32_External_Rela *)
+ srelgot->contents)
+ + srelgot->reloc_count));
+ ++ srelgot->reloc_count;
+ outrel.r_info = ELF32_R_INFO (0, R_MN10300_TLS_DTPMOD);
+ break;
+ case R_MN10300_TLS_GOTIE:
+ case R_MN10300_TLS_IE:
+ outrel.r_info = ELF32_R_INFO (0, R_MN10300_TLS_TPOFF);
+ break;
+ default:
+ outrel.r_info = ELF32_R_INFO (0, R_MN10300_RELATIVE);
+ break;
+ }
+
outrel.r_addend = value;
bfd_elf32_swap_reloca_out (output_bfd, &outrel,
(bfd_byte *) (((Elf32_External_Rela *)
srelgot->contents)
+ srelgot->reloc_count));
++ srelgot->reloc_count;
+ elf_local_got_offsets (input_bfd)[symndx] |= 1;
}
- value = sgot->output_offset + off;
+ value = sgot->output_offset + (off & ~(bfd_vma) 1);
}
- }
+ }
value += addend;
- if (r_type == R_MN10300_GOT32)
+ if (r_type == R_MN10300_TLS_IE)
+ {
+ value += sgot->output_section->vma;
+ bfd_put_32 (input_bfd, value, hit_data);
+ return bfd_reloc_ok;
+ }
+ else if (r_type == R_MN10300_TLS_GOTIE
+ || r_type == R_MN10300_TLS_GD
+ || r_type == R_MN10300_TLS_LD)
+ {
+ bfd_put_32 (input_bfd, value, hit_data);
+ return bfd_reloc_ok;
+ }
+ else if (r_type == R_MN10300_GOT32)
{
bfd_put_32 (input_bfd, value, hit_data);
return bfd_reloc_ok;
Elf_Internal_Shdr *symtab_hdr;
struct elf_link_hash_entry **sym_hashes;
Elf_Internal_Rela *rel, *relend;
+ Elf_Internal_Rela * trel;
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
struct elf32_mn10300_link_hash_entry *h;
bfd_vma relocation;
bfd_reloc_status_type r;
+ int tls_r_type;
+ bfd_boolean unresolved_reloc = FALSE;
+ bfd_boolean warned, ignored;
+ struct elf_link_hash_entry * hh;
+ relocation = 0;
r_symndx = ELF32_R_SYM (rel->r_info);
r_type = ELF32_R_TYPE (rel->r_info);
howto = elf_mn10300_howto_table + r_type;
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);
- }
+ hh = NULL;
else
{
- bfd_boolean unresolved_reloc;
- bfd_boolean warned;
- struct elf_link_hash_entry *hh;
-
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
hh, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
+ }
+ h = elf_mn10300_hash_entry (hh);
- h = (struct elf32_mn10300_link_hash_entry *) hh;
+ tls_r_type = elf_mn10300_tls_transition (info, r_type, hh, input_section, 0);
+ if (tls_r_type != r_type)
+ {
+ bfd_boolean had_plt;
+
+ had_plt = mn10300_do_tls_transition (input_bfd, r_type, tls_r_type,
+ contents, rel->r_offset);
+ r_type = tls_r_type;
+ howto = elf_mn10300_howto_table + r_type;
+
+ if (had_plt)
+ for (trel = rel+1; trel < relend; trel++)
+ if ((ELF32_R_TYPE (trel->r_info) == R_MN10300_PLT32
+ || ELF32_R_TYPE (trel->r_info) == R_MN10300_PCREL32)
+ && rel->r_offset + had_plt == trel->r_offset)
+ trel->r_info = ELF32_R_INFO (0, R_MN10300_NONE);
+ }
+ 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);
+ }
+ else
+ {
if ((h->root.root.type == bfd_link_hash_defined
|| h->root.root.type == bfd_link_hash_defweak)
&& ( r_type == R_MN10300_GOTPC32
&& h->root.plt.offset != (bfd_vma) -1)
|| (( r_type == R_MN10300_GOT32
|| r_type == R_MN10300_GOT24
+ || r_type == R_MN10300_TLS_GD
+ || r_type == R_MN10300_TLS_LD
+ || r_type == R_MN10300_TLS_GOTIE
+ || r_type == R_MN10300_TLS_IE
|| r_type == R_MN10300_GOT16)
&& elf_hash_table (info)->dynamic_sections_created
&& !SYMBOL_REFERENCES_LOCAL (info, hh))
/* _32 relocs in executables force _COPY relocs,
such that the address of the symbol ends up
being local. */
- && !info->executable
+ && !bfd_link_executable (info)
&& !SYMBOL_REFERENCES_LOCAL (info, hh)
&& ((input_section->flags & SEC_ALLOC) != 0
/* DWARF will emit R_MN10300_32 relocations
obscure cases sec->output_section will be NULL. */
relocation = 0;
- else if (!info->relocatable && unresolved_reloc)
- (*_bfd_error_handler)
+ else if (!bfd_link_relocatable (info) && unresolved_reloc
+ && _bfd_elf_section_offset (output_bfd, info, input_section,
+ rel->r_offset) != (bfd_vma) -1)
+
+ _bfd_error_handler
+ /* xgettext:c-format */
(_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
input_bfd,
input_section,
h->root.root.root.string);
}
- if (sec != NULL && elf_discarded_section (sec))
+ if (sec != NULL && discarded_section (sec))
RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
- rel, relend, howto, contents);
+ rel, 1, relend, howto, 0, contents);
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
continue;
r = mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd,
switch (r)
{
case bfd_reloc_overflow:
- if (! ((*info->callbacks->reloc_overflow)
- (info, (h ? &h->root.root : NULL), name,
- howto->name, (bfd_vma) 0, input_bfd,
- input_section, rel->r_offset)))
- return FALSE;
+ (*info->callbacks->reloc_overflow)
+ (info, (h ? &h->root.root : NULL), name, howto->name,
+ (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
break;
case bfd_reloc_undefined:
- if (! ((*info->callbacks->undefined_symbol)
- (info, name, input_bfd, input_section,
- rel->r_offset, TRUE)))
- return FALSE;
+ (*info->callbacks->undefined_symbol)
+ (info, name, input_bfd, input_section, rel->r_offset, TRUE);
break;
case bfd_reloc_outofrange:
if (r_type == R_MN10300_PCREL32)
msg = _("error: inappropriate relocation type for shared"
" library (did you forget -fpic?)");
+ else if (r_type == R_MN10300_GOT32)
+ /* xgettext:c-format */
+ msg = _("%B: taking the address of protected function"
+ " '%s' cannot be done when making a shared library");
else
msg = _("internal error: suspicious relocation type used"
" in shared library");
/* Fall through. */
common_error:
- if (!((*info->callbacks->warning)
- (info, msg, name, input_bfd, input_section,
- rel->r_offset)))
- return FALSE;
- break;
+ _bfd_error_handler (msg, input_bfd, name);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
}
}
}
entry = (struct elf32_mn10300_link_hash_entry *) gen_entry;
- if (entry->root.root.type == bfd_link_hash_warning)
- entry = (struct elf32_mn10300_link_hash_entry *) entry->root.root.u.i.link;
-
/* If we already know we want to convert "call" to "calls" for calls
to this symbol, then return now. */
if (entry->flags == MN10300_CONVERT_CALL_TO_CALLS)
serve to keep the section artifically inflated. */
if (ELF32_R_TYPE ((irelend - 1)->r_info) == (int) R_MN10300_ALIGN)
--irelend;
-
+
/* The deletion must stop at the next ALIGN reloc for an aligment
power larger than, or not a multiple of, the number of bytes we
are deleting. */
asection *section = sec;
bfd_vma align_gap_adjustment;
- if (link_info->relocatable)
+ if (bfd_link_relocatable (link_info))
(*link_info->callbacks->einfo)
(_("%P%F: --relax and -r may not be used together\n"));
/* Iterate over all the input bfds. */
for (input_bfd = link_info->input_bfds;
input_bfd != NULL;
- input_bfd = input_bfd->link_next)
+ input_bfd = input_bfd->link.next)
{
/* We're going to need all the symbols for each bfd. */
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
a "call" instruction. */
for (input_bfd = link_info->input_bfds;
input_bfd != NULL;
- input_bfd = input_bfd->link_next)
+ input_bfd = input_bfd->link.next)
{
/* We're going to need all the local symbols for each bfd. */
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
{
int bytes = 0;
bfd_vma symval;
+ struct elf_link_hash_entry **hh;
/* Note that we've changed things. */
elf_section_data (section)->relocs = internal_relocs;
bytes))
goto error_return;
+ /* There may be other C++ functions symbols with the same
+ address. If so then mark these as having had their
+ prologue bytes deleted as well. */
+ for (hh = elf_sym_hashes (input_bfd); hh < end_hashes; hh++)
+ {
+ struct elf32_mn10300_link_hash_entry *h;
+
+ h = (struct elf32_mn10300_link_hash_entry *) * hh;
+
+ if (h != sym_hash
+ && (h->root.root.type == bfd_link_hash_defined
+ || h->root.root.type == bfd_link_hash_defweak)
+ && h->root.root.u.def.section == section
+ && ! (h->flags & MN10300_CONVERT_CALL_TO_CALLS)
+ && h->root.root.u.def.value == symval
+ && h->root.type == STT_FUNC)
+ h->flags |= MN10300_DELETED_PROLOGUE_BYTES;
+ }
+
/* Something changed. Not strictly necessary, but
may lead to more relaxing opportunities. */
*again = TRUE;
/* We don't have to do anything for a relocatable link, if
this section does not have relocs, or if this is not a
code section. */
- if (link_info->relocatable
+ if (bfd_link_relocatable (link_info)
|| (sec->flags & SEC_RELOC) == 0
|| sec->reloc_count == 0
|| (sec->flags & SEC_CODE) == 0)
isym->st_name);
if ((sym_sec->flags & SEC_MERGE)
- && sym_sec->sec_info_type == ELF_INFO_TYPE_MERGE)
+ && sym_sec->sec_info_type == SEC_INFO_TYPE_MERGE)
{
symval = isym->st_value;
{
asection * splt;
- splt = bfd_get_section_by_name (elf_hash_table (link_info)
- ->dynobj, ".plt");
-
+ splt = hash_table->root.splt;
value = ((splt->output_section->vma
+ splt->output_offset
+ h->root.plt.offset)
{
asection * sgot;
- sgot = bfd_get_section_by_name (elf_hash_table (link_info)
- ->dynobj, ".got");
-
+ sgot = hash_table->root.sgot;
if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_GOT32)
{
value = sgot->output_offset;
&& (value & 0x8000))
continue;
- /* mov imm16, an zero-extends the immediate. */
- if (code == 0xdc
+ /* "mov imm16, an" zero-extends the immediate. */
+ if ((code & 0xfc) == 0xdc
&& (long) value < 0)
continue;
ret->movm_stack_size = 0;
ret->flags = 0;
ret->value = 0;
+ ret->tls_type = GOT_UNKNOWN;
}
return (struct bfd_hash_entry *) ret;
}
+static void
+_bfd_mn10300_copy_indirect_symbol (struct bfd_link_info * info,
+ struct elf_link_hash_entry * dir,
+ struct elf_link_hash_entry * ind)
+{
+ struct elf32_mn10300_link_hash_entry * edir;
+ struct elf32_mn10300_link_hash_entry * eind;
+
+ edir = elf_mn10300_hash_entry (dir);
+ eind = elf_mn10300_hash_entry (ind);
+
+ if (ind->root.type == bfd_link_hash_indirect
+ && dir->got.refcount <= 0)
+ {
+ edir->tls_type = eind->tls_type;
+ eind->tls_type = GOT_UNKNOWN;
+ }
+ edir->direct_calls = eind->direct_calls;
+ edir->stack_size = eind->stack_size;
+ edir->movm_args = eind->movm_args;
+ edir->movm_stack_size = eind->movm_stack_size;
+ edir->flags = eind->flags;
+
+ _bfd_elf_link_hash_copy_indirect (info, dir, ind);
+}
+
+/* Destroy an mn10300 ELF linker hash table. */
+
+static void
+elf32_mn10300_link_hash_table_free (bfd *obfd)
+{
+ struct elf32_mn10300_link_hash_table *ret
+ = (struct elf32_mn10300_link_hash_table *) obfd->link.hash;
+
+ obfd->link.hash = &ret->static_hash_table->root.root;
+ _bfd_elf_link_hash_table_free (obfd);
+ obfd->is_linker_output = TRUE;
+ obfd->link.hash = &ret->root.root;
+ _bfd_elf_link_hash_table_free (obfd);
+}
+
/* Create an mn10300 ELF linker hash table. */
static struct bfd_link_hash_table *
struct elf32_mn10300_link_hash_table *ret;
bfd_size_type amt = sizeof (* ret);
- ret = bfd_malloc (amt);
+ ret = bfd_zmalloc (amt);
if (ret == NULL)
return NULL;
- if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
- elf32_mn10300_link_hash_newfunc,
- sizeof (struct elf32_mn10300_link_hash_entry),
- MN10300_ELF_DATA))
- {
- free (ret);
- return NULL;
- }
-
- ret->flags = 0;
amt = sizeof (struct elf_link_hash_table);
- ret->static_hash_table = bfd_malloc (amt);
+ ret->static_hash_table = bfd_zmalloc (amt);
if (ret->static_hash_table == NULL)
{
free (ret);
free (ret);
return NULL;
}
- return & ret->root.root;
-}
-/* Free an mn10300 ELF linker hash table. */
+ abfd->is_linker_output = FALSE;
+ abfd->link.hash = NULL;
+ if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+ elf32_mn10300_link_hash_newfunc,
+ sizeof (struct elf32_mn10300_link_hash_entry),
+ MN10300_ELF_DATA))
+ {
+ abfd->is_linker_output = TRUE;
+ abfd->link.hash = &ret->static_hash_table->root.root;
+ _bfd_elf_link_hash_table_free (abfd);
+ free (ret);
+ return NULL;
+ }
+ ret->root.root.hash_table_free = elf32_mn10300_link_hash_table_free;
-static void
-elf32_mn10300_link_hash_table_free (struct bfd_link_hash_table *hash)
-{
- struct elf32_mn10300_link_hash_table *ret
- = (struct elf32_mn10300_link_hash_table *) hash;
+ ret->tls_ldm_got.offset = -1;
- _bfd_generic_link_hash_table_free
- ((struct bfd_link_hash_table *) ret->static_hash_table);
- _bfd_generic_link_hash_table_free
- ((struct bfd_link_hash_table *) ret);
+ return & ret->root.root;
}
static unsigned long
object file when linking. */
static bfd_boolean
-_bfd_mn10300_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
+_bfd_mn10300_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
{
+ bfd *obfd = info->output_bfd;
+
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
return TRUE;
/* Return size of the first PLT entry. */
#define elf_mn10300_sizeof_plt0(info) \
- (info->shared ? PIC_PLT_ENTRY_SIZE : PLT0_ENTRY_SIZE)
+ (bfd_link_pic (info) ? PIC_PLT_ENTRY_SIZE : PLT0_ENTRY_SIZE)
/* Return size of a PLT entry. */
#define elf_mn10300_sizeof_plt(info) \
- (info->shared ? PIC_PLT_ENTRY_SIZE : PLT_ENTRY_SIZE)
+ (bfd_link_pic (info) ? PIC_PLT_ENTRY_SIZE : PLT_ENTRY_SIZE)
/* Return offset of the PLT0 address in an absolute PLT entry. */
#define elf_mn10300_plt_plt0_offset(info) 16
flagword flags;
asection * s;
const struct elf_backend_data * bed = get_elf_backend_data (abfd);
+ struct elf32_mn10300_link_hash_table *htab = elf32_mn10300_hash_table (info);
int ptralign = 0;
switch (bed->s->arch_size)
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
| SEC_LINKER_CREATED);
- s = bfd_make_section_with_flags (abfd,
- (bed->default_use_rela_p
- ? ".rela.plt" : ".rel.plt"),
- flags | SEC_READONLY);
+ s = bfd_make_section_anyway_with_flags (abfd,
+ (bed->default_use_rela_p
+ ? ".rela.plt" : ".rel.plt"),
+ flags | SEC_READONLY);
+ htab->root.srelplt = s;
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, ptralign))
return FALSE;
if (! _bfd_mn10300_elf_create_got_section (abfd, info))
return FALSE;
- {
- const char * secname;
- char * relname;
- flagword secflags;
- asection * sec;
-
- for (sec = abfd->sections; sec; sec = sec->next)
- {
- secflags = bfd_get_section_flags (abfd, sec);
- if ((secflags & (SEC_DATA | SEC_LINKER_CREATED))
- || ((secflags & SEC_HAS_CONTENTS) != SEC_HAS_CONTENTS))
- continue;
-
- secname = bfd_get_section_name (abfd, sec);
- relname = bfd_malloc (strlen (secname) + 6);
- strcpy (relname, ".rela");
- strcat (relname, secname);
-
- s = bfd_make_section_with_flags (abfd, relname,
- flags | SEC_READONLY);
- if (s == NULL
- || ! bfd_set_section_alignment (abfd, s, ptralign))
- return FALSE;
- }
- }
-
if (bed->want_dynbss)
{
/* The .dynbss section is a place to put symbols which are defined
image and use a R_*_COPY reloc to tell the dynamic linker to
initialize them at run time. The linker script puts the .dynbss
section into the .bss section of the final image. */
- s = bfd_make_section_with_flags (abfd, ".dynbss",
- SEC_ALLOC | SEC_LINKER_CREATED);
+ s = bfd_make_section_anyway_with_flags (abfd, ".dynbss",
+ SEC_ALLOC | SEC_LINKER_CREATED);
if (s == NULL)
return FALSE;
be needed, we can discard it later. We will never need this
section when generating a shared object, since they do not use
copy relocs. */
- if (! info->shared)
+ if (! bfd_link_pic (info))
{
- s = bfd_make_section_with_flags (abfd,
- (bed->default_use_rela_p
- ? ".rela.bss" : ".rel.bss"),
- flags | SEC_READONLY);
+ s = bfd_make_section_anyway_with_flags (abfd,
+ (bed->default_use_rela_p
+ ? ".rela.bss" : ".rel.bss"),
+ flags | SEC_READONLY);
if (s == NULL
|| ! bfd_set_section_alignment (abfd, s, ptralign))
return FALSE;
_bfd_mn10300_elf_adjust_dynamic_symbol (struct bfd_link_info * info,
struct elf_link_hash_entry * h)
{
+ struct elf32_mn10300_link_hash_table *htab = elf32_mn10300_hash_table (info);
bfd * dynobj;
asection * s;
- dynobj = elf_hash_table (info)->dynobj;
+ dynobj = htab->root.dynobj;
/* Make sure we know what is going on here. */
BFD_ASSERT (dynobj != NULL
if (h->type == STT_FUNC
|| h->needs_plt)
{
- if (! info->shared
+ if (! bfd_link_pic (info)
&& !h->def_dynamic
&& !h->ref_dynamic)
{
return FALSE;
}
- s = bfd_get_section_by_name (dynobj, ".plt");
+ s = htab->root.splt;
BFD_ASSERT (s != NULL);
/* If this is the first .plt entry, make room for the special
location in the .plt. This is required to make function
pointers compare as equal between the normal executable and
the shared library. */
- if (! info->shared
+ if (! bfd_link_pic (info)
&& !h->def_regular)
{
h->root.u.def.section = s;
/* We also need to make an entry in the .got.plt section, which
will be placed in the .got section by the linker script. */
- s = bfd_get_section_by_name (dynobj, ".got.plt");
+ s = htab->root.sgotplt;
BFD_ASSERT (s != NULL);
s->size += 4;
/* We also need to make an entry in the .rela.plt section. */
- s = bfd_get_section_by_name (dynobj, ".rela.plt");
+ s = htab->root.srelplt;
BFD_ASSERT (s != NULL);
s->size += sizeof (Elf32_External_Rela);
only references to the symbol are via the global offset table.
For such cases we need not do anything here; the relocations will
be handled correctly by relocate_section. */
- if (info->shared)
+ if (bfd_link_pic (info))
return TRUE;
/* If there are no references to this symbol that do not use the
if (!h->non_got_ref)
return TRUE;
- if (h->size == 0)
- {
- (*_bfd_error_handler) (_("dynamic variable `%s' is zero size"),
- h->root.root.string);
- return TRUE;
- }
-
/* We must allocate the symbol in our .dynbss section, which will
become part of the .bss section of the executable. There will be
an entry for this symbol in the .dynsym section. The dynamic
both the dynamic object and the regular object will refer to the
same memory location for the variable. */
- s = bfd_get_section_by_name (dynobj, ".dynbss");
+ s = bfd_get_linker_section (dynobj, ".dynbss");
BFD_ASSERT (s != NULL);
/* We must generate a R_MN10300_COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
.rela.bss section we are going to use. */
- if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
asection * srel;
- srel = bfd_get_section_by_name (dynobj, ".rela.bss");
+ srel = bfd_get_linker_section (dynobj, ".rela.bss");
BFD_ASSERT (srel != NULL);
srel->size += sizeof (Elf32_External_Rela);
h->needs_copy = 1;
}
- return _bfd_elf_adjust_dynamic_copy (h, s);
+ return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
/* Set the sizes of the dynamic sections. */
_bfd_mn10300_elf_size_dynamic_sections (bfd * output_bfd,
struct bfd_link_info * info)
{
+ struct elf32_mn10300_link_hash_table *htab = elf32_mn10300_hash_table (info);
bfd * dynobj;
asection * s;
bfd_boolean plt;
bfd_boolean relocs;
bfd_boolean reltext;
- dynobj = elf_hash_table (info)->dynobj;
+ dynobj = htab->root.dynobj;
BFD_ASSERT (dynobj != NULL);
if (elf_hash_table (info)->dynamic_sections_created)
{
/* Set the contents of the .interp section to the interpreter. */
- if (info->executable)
+ if (bfd_link_executable (info) && !info->nointerp)
{
- s = bfd_get_section_by_name (dynobj, ".interp");
+ s = bfd_get_linker_section (dynobj, ".interp");
BFD_ASSERT (s != NULL);
s->size = sizeof ELF_DYNAMIC_INTERPRETER;
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
not actually use these entries. Reset the size of .rela.got,
which will cause it to get stripped from the output file
below. */
- s = bfd_get_section_by_name (dynobj, ".rela.got");
+ s = htab->root.sgot;
if (s != NULL)
s->size = 0;
}
+ if (htab->tls_ldm_got.refcount > 0)
+ {
+ s = htab->root.srelgot;
+ BFD_ASSERT (s != NULL);
+ s->size += sizeof (Elf32_External_Rela);
+ }
+
/* The check_relocs and adjust_dynamic_symbol entry points have
determined the sizes of the various dynamic sections. Allocate
memory for them. */
but we must add the entries now so that we get the correct
size for the .dynamic section. The DT_DEBUG entry is filled
in by the dynamic linker and used by the debugger. */
- if (! info->shared)
+ if (! bfd_link_pic (info))
{
if (!_bfd_elf_add_dynamic_entry (info, DT_DEBUG, 0))
return FALSE;
struct elf_link_hash_entry * h,
Elf_Internal_Sym * sym)
{
+ struct elf32_mn10300_link_hash_table *htab = elf32_mn10300_hash_table (info);
bfd * dynobj;
- dynobj = elf_hash_table (info)->dynobj;
+ dynobj = htab->root.dynobj;
if (h->plt.offset != (bfd_vma) -1)
{
BFD_ASSERT (h->dynindx != -1);
- splt = bfd_get_section_by_name (dynobj, ".plt");
- sgot = bfd_get_section_by_name (dynobj, ".got.plt");
- srel = bfd_get_section_by_name (dynobj, ".rela.plt");
+ splt = htab->root.splt;
+ sgot = htab->root.sgotplt;
+ srel = htab->root.srelplt;
BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
/* Get the index in the procedure linkage table which
got_offset = (plt_index + 3) * 4;
/* Fill in the entry in the procedure linkage table. */
- if (! info->shared)
+ if (! bfd_link_pic (info))
{
memcpy (splt->contents + h->plt.offset, elf_mn10300_plt_entry,
elf_mn10300_sizeof_plt (info));
Elf_Internal_Rela rel;
/* This symbol has an entry in the global offset table. Set it up. */
- sgot = bfd_get_section_by_name (dynobj, ".got");
- srel = bfd_get_section_by_name (dynobj, ".rela.got");
+ sgot = htab->root.sgot;
+ srel = htab->root.srelgot;
BFD_ASSERT (sgot != NULL && srel != NULL);
rel.r_offset = (sgot->output_section->vma
+ sgot->output_offset
+ (h->got.offset & ~1));
- /* If this is a -Bsymbolic link, and the symbol is defined
- locally, we just want to emit a RELATIVE reloc. Likewise if
- the symbol was forced to be local because of a version file.
- The entry in the global offset table will already have been
- initialized in the relocate_section function. */
- if (info->shared
- && (info->symbolic || h->dynindx == -1)
- && h->def_regular)
- {
- rel.r_info = ELF32_R_INFO (0, R_MN10300_RELATIVE);
- rel.r_addend = (h->root.u.def.value
- + h->root.u.def.section->output_section->vma
- + h->root.u.def.section->output_offset);
- }
- else
+ switch (elf_mn10300_hash_entry (h)->tls_type)
{
+ case GOT_TLS_GD:
bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset);
- rel.r_info = ELF32_R_INFO (h->dynindx, R_MN10300_GLOB_DAT);
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset + 4);
+ rel.r_info = ELF32_R_INFO (h->dynindx, R_MN10300_TLS_DTPMOD);
rel.r_addend = 0;
+ bfd_elf32_swap_reloca_out (output_bfd, & rel,
+ (bfd_byte *) ((Elf32_External_Rela *) srel->contents
+ + srel->reloc_count));
+ ++ srel->reloc_count;
+ rel.r_info = ELF32_R_INFO (h->dynindx, R_MN10300_TLS_DTPOFF);
+ rel.r_offset += 4;
+ rel.r_addend = 0;
+ break;
+
+ case GOT_TLS_IE:
+ /* We originally stored the addend in the GOT, but at this
+ point, we want to move it to the reloc instead as that's
+ where the dynamic linker wants it. */
+ rel.r_addend = bfd_get_32 (output_bfd, sgot->contents + h->got.offset);
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset);
+ if (h->dynindx == -1)
+ rel.r_info = ELF32_R_INFO (0, R_MN10300_TLS_TPOFF);
+ else
+ rel.r_info = ELF32_R_INFO (h->dynindx, R_MN10300_TLS_TPOFF);
+ break;
+
+ default:
+ /* If this is a -Bsymbolic link, and the symbol is defined
+ locally, we just want to emit a RELATIVE reloc. Likewise if
+ the symbol was forced to be local because of a version file.
+ The entry in the global offset table will already have been
+ initialized in the relocate_section function. */
+ if (bfd_link_pic (info)
+ && (info->symbolic || h->dynindx == -1)
+ && h->def_regular)
+ {
+ rel.r_info = ELF32_R_INFO (0, R_MN10300_RELATIVE);
+ rel.r_addend = (h->root.u.def.value
+ + h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset);
+ }
+ else
+ {
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got.offset);
+ rel.r_info = ELF32_R_INFO (h->dynindx, R_MN10300_GLOB_DAT);
+ rel.r_addend = 0;
+ }
}
- bfd_elf32_swap_reloca_out (output_bfd, &rel,
- (bfd_byte *) ((Elf32_External_Rela *) srel->contents
- + srel->reloc_count));
- ++ srel->reloc_count;
+ if (ELF32_R_TYPE (rel.r_info) != R_MN10300_NONE)
+ {
+ bfd_elf32_swap_reloca_out (output_bfd, &rel,
+ (bfd_byte *) ((Elf32_External_Rela *) srel->contents
+ + srel->reloc_count));
+ ++ srel->reloc_count;
+ }
}
if (h->needs_copy)
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak));
- s = bfd_get_section_by_name (h->root.u.def.section->owner,
- ".rela.bss");
+ s = bfd_get_linker_section (dynobj, ".rela.bss");
BFD_ASSERT (s != NULL);
rel.r_offset = (h->root.u.def.value
}
/* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
- if (streq (h->root.root.string, "_DYNAMIC")
+ if (h == elf_hash_table (info)->hdynamic
|| h == elf_hash_table (info)->hgot)
sym->st_shndx = SHN_ABS;
bfd * dynobj;
asection * sgot;
asection * sdyn;
+ struct elf32_mn10300_link_hash_table *htab = elf32_mn10300_hash_table (info);
- dynobj = elf_hash_table (info)->dynobj;
-
- sgot = bfd_get_section_by_name (dynobj, ".got.plt");
+ dynobj = htab->root.dynobj;
+ sgot = htab->root.sgotplt;
BFD_ASSERT (sgot != NULL);
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+ sdyn = bfd_get_linker_section (dynobj, ".dynamic");
if (elf_hash_table (info)->dynamic_sections_created)
{
for (; dyncon < dynconend; dyncon++)
{
Elf_Internal_Dyn dyn;
- const char * name;
asection * s;
bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
break;
case DT_PLTGOT:
- name = ".got";
+ s = htab->root.sgot;
goto get_vma;
case DT_JMPREL:
- name = ".rela.plt";
+ s = htab->root.srelplt;
get_vma:
- s = bfd_get_section_by_name (output_bfd, name);
- BFD_ASSERT (s != NULL);
- dyn.d_un.d_ptr = s->vma;
+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
break;
case DT_PLTRELSZ:
- s = bfd_get_section_by_name (output_bfd, ".rela.plt");
- BFD_ASSERT (s != NULL);
+ s = htab->root.srelplt;
dyn.d_un.d_val = s->size;
bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
break;
-
- case DT_RELASZ:
- /* My reading of the SVR4 ABI indicates that the
- procedure linkage table relocs (DT_JMPREL) should be
- included in the overall relocs (DT_RELA). This is
- what Solaris does. However, UnixWare can not handle
- that case. Therefore, we override the DT_RELASZ entry
- here to make it not include the JMPREL relocs. Since
- the linker script arranges for .rela.plt to follow all
- other relocation sections, we don't have to worry
- about changing the DT_RELA entry. */
- s = bfd_get_section_by_name (output_bfd, ".rela.plt");
- if (s != NULL)
- dyn.d_un.d_val -= s->size;
- bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
- break;
}
}
/* Fill in the first entry in the procedure linkage table. */
- splt = bfd_get_section_by_name (dynobj, ".plt");
+ splt = htab->root.splt;
if (splt && splt->size > 0)
{
- if (info->shared)
+ if (bfd_link_pic (info))
{
memcpy (splt->contents, elf_mn10300_pic_plt_entry,
elf_mn10300_sizeof_plt (info));
/* UnixWare sets the entsize of .plt to 4, although that doesn't
really seem like the right value. */
elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
+
+ /* UnixWare sets the entsize of .plt to 4, but this is incorrect
+ as it means that the size of the PLT0 section (15 bytes) is not
+ a multiple of the sh_entsize. Some ELF tools flag this as an
+ error. We could pad PLT0 to 16 bytes, but that would introduce
+ compatibilty issues with previous toolchains, so instead we
+ just set the entry size to 1. */
+ elf_section_data (splt->output_section)->this_hdr.sh_entsize = 1;
}
}
properly. */
static enum elf_reloc_type_class
-_bfd_mn10300_elf_reloc_type_class (const Elf_Internal_Rela *rela)
+_bfd_mn10300_elf_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ const asection *rel_sec ATTRIBUTE_UNUSED,
+ const Elf_Internal_Rela *rela)
{
switch ((int) ELF32_R_TYPE (rela->r_info))
{
static bfd_boolean
mn10300_elf_mkobject (bfd *abfd)
{
- /* We do not actually need any extra room in the bfd elf data structure.
- But we do need the object_id of the structure to be set to
- MN10300_ELF_DATA so that elflink.c:elf_link_add_object_symols() will call
- our mn10300_elf_check_relocs function which will then allocate space in
- the .got section for any GOT based relocs. */
- return bfd_elf_allocate_object (abfd, sizeof (struct elf_obj_tdata),
+ return bfd_elf_allocate_object (abfd, sizeof (struct elf_mn10300_obj_tdata),
MN10300_ELF_DATA);
}
#define bfd_elf32_mkobject mn10300_elf_mkobject
#ifndef ELF_ARCH
-#define TARGET_LITTLE_SYM bfd_elf32_mn10300_vec
+#define TARGET_LITTLE_SYM mn10300_elf32_vec
#define TARGET_LITTLE_NAME "elf32-mn10300"
#define ELF_ARCH bfd_arch_mn10300
#define ELF_TARGET_ID MN10300_ELF_DATA
mn10300_elf_get_relocated_section_contents
#define bfd_elf32_bfd_link_hash_table_create \
elf32_mn10300_link_hash_table_create
-#define bfd_elf32_bfd_link_hash_table_free \
- elf32_mn10300_link_hash_table_free
#ifndef elf_symbol_leading_char
#define elf_symbol_leading_char '_'
_bfd_mn10300_elf_finish_dynamic_symbol
#define elf_backend_finish_dynamic_sections \
_bfd_mn10300_elf_finish_dynamic_sections
-
+#define elf_backend_copy_indirect_symbol \
+ _bfd_mn10300_copy_indirect_symbol
#define elf_backend_reloc_type_class \
_bfd_mn10300_elf_reloc_type_class
#define elf_backend_plt_readonly 1
#define elf_backend_want_plt_sym 0
#define elf_backend_got_header_size 12
+#define elf_backend_dtrel_excludes_plt 1
#include "elf32-target.h"