| Index: bfd/elf-m10300.c
|
| diff --git a/bfd/elf-m10300.c b/bfd/elf-m10300.c
|
| index fa33b4a2fbe19f6be4b9549b0b68feba80242175..709ea161eb1a026d8f14910277ac4326537128f7 100644
|
| --- a/bfd/elf-m10300.c
|
| +++ b/bfd/elf-m10300.c
|
| @@ -1,6 +1,6 @@
|
| /* Matsushita 10300 specific support for 32-bit ELF
|
| Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
| - 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
| + 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
|
|
|
| This file is part of BFD, the Binary File Descriptor library.
|
|
|
| @@ -69,6 +69,14 @@ struct elf32_mn10300_link_hash_entry
|
|
|
| /* 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
|
| @@ -87,8 +95,31 @@ struct elf32_mn10300_link_hash_table
|
| /* 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
|
| @@ -448,15 +479,131 @@ static reloc_howto_type elf_mn10300_howto_table[] =
|
| 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 */
|
| @@ -519,6 +666,15 @@ static const struct mn10300_reloc_map mn10300_reloc_map[] =
|
| { 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 }
|
| };
|
| @@ -534,10 +690,12 @@ _bfd_mn10300_elf_create_got_section (bfd * abfd,
|
| 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)
|
| @@ -565,7 +723,8 @@ _bfd_mn10300_elf_create_got_section (bfd * abfd,
|
| 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;
|
| @@ -576,19 +735,21 @@ _bfd_mn10300_elf_create_got_section (bfd * abfd,
|
| {
|
| 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;
|
| @@ -599,7 +760,7 @@ _bfd_mn10300_elf_create_got_section (bfd * abfd,
|
| 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;
|
|
|
| @@ -650,6 +811,223 @@ mn10300_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
|
| 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 (info->shared)
|
| + 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)
|
| + (_("%s: Unsupported transition from %s to %s"),
|
| + bfd_get_filename (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. */
|
| @@ -660,6 +1038,7 @@ mn10300_elf_check_relocs (bfd *abfd,
|
| 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;
|
| @@ -694,6 +1073,7 @@ mn10300_elf_check_relocs (bfd *abfd,
|
| 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)
|
| @@ -707,6 +1087,7 @@ mn10300_elf_check_relocs (bfd *abfd,
|
| }
|
|
|
| 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)
|
| @@ -721,6 +1102,10 @@ mn10300_elf_check_relocs (bfd *abfd,
|
| 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;
|
| @@ -749,53 +1134,101 @@ mn10300_elf_check_relocs (bfd *abfd,
|
| 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 (info->shared)
|
| + 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. */
|
|
|
| + switch (r_type)
|
| + {
|
| + 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 (sgot == NULL)
|
| {
|
| - sgot = bfd_get_section_by_name (dynobj, ".got");
|
| + sgot = htab->root.sgot;
|
| BFD_ASSERT (sgot != NULL);
|
| }
|
|
|
| if (srelgot == NULL
|
| && (h != NULL || info->shared))
|
| {
|
| - srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
|
| + srelgot = bfd_get_linker_section (dynobj, ".rela.got");
|
| if (srelgot == NULL)
|
| {
|
| - srelgot = bfd_make_section_with_flags (dynobj,
|
| - ".rela.got",
|
| - (SEC_ALLOC
|
| - | SEC_LOAD
|
| - | SEC_HAS_CONTENTS
|
| - | SEC_IN_MEMORY
|
| - | SEC_LINKER_CREATED
|
| - | SEC_READONLY));
|
| + flagword flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
|
| + | SEC_IN_MEMORY | SEC_LINKER_CREATED
|
| + | SEC_READONLY);
|
| + srelgot = bfd_make_section_anyway_with_flags (dynobj,
|
| + ".rela.got",
|
| + flags);
|
| if (srelgot == NULL
|
| || ! bfd_set_section_alignment (dynobj, srelgot, 2))
|
| goto fail;
|
| }
|
| }
|
|
|
| - if (h != 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)
|
| + {
|
| + if (elf_mn10300_hash_entry (h)->tls_type != tls_type
|
| + && elf_mn10300_hash_entry (h)->tls_type != GOT_UNKNOWN)
|
| + {
|
| + 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)
|
| + (_("%B: %s' accessed both as normal and thread local symbol"),
|
| + abfd, h ? h->root.root.string : "<local>");
|
| + }
|
| +
|
| + 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
|
| {
|
| @@ -806,13 +1239,15 @@ mn10300_elf_check_relocs (bfd *abfd,
|
| 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;
|
| @@ -825,14 +1260,26 @@ mn10300_elf_check_relocs (bfd *abfd,
|
| 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 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:
|
| @@ -873,6 +1320,7 @@ mn10300_elf_check_relocs (bfd *abfd,
|
| 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
|
| @@ -981,6 +1429,7 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto,
|
| 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;
|
| @@ -1012,6 +1461,17 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto,
|
| && h != NULL
|
| && ! SYMBOL_REFERENCES_LOCAL (info, h))
|
| return bfd_reloc_dangerous;
|
| + 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 (info->shared
|
| + && (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;
|
| }
|
|
|
| is_sym_diff_reloc = FALSE;
|
| @@ -1208,9 +1668,11 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto,
|
| 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;
|
| @@ -1220,9 +1682,11 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto,
|
| 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;
|
| @@ -1235,16 +1699,20 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto,
|
| 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)
|
| @@ -1256,8 +1724,10 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto,
|
| 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)
|
| @@ -1272,8 +1742,10 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto,
|
| && 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;
|
| @@ -1293,8 +1765,10 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto,
|
| && 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;
|
| @@ -1311,41 +1785,100 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto,
|
| 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 = bfd_get_linker_section (dynobj, ".rela.got");
|
| + 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);
|
| +
|
| + 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;
|
|
|
| - off = h->got.offset;
|
| - BFD_ASSERT (off != (bfd_vma) -1);
|
| + off = elf_local_got_offsets (input_bfd)[symndx];
|
|
|
| - 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;
|
| - }
|
| + 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)
|
| @@ -1353,28 +1886,64 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto,
|
| asection * srelgot;
|
| Elf_Internal_Rela outrel;
|
|
|
| - srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
|
| + srelgot = bfd_get_linker_section (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;
|
| @@ -1419,6 +1988,7 @@ mn10300_elf_relocate_section (bfd *output_bfd,
|
| 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);
|
| @@ -1435,7 +2005,12 @@ mn10300_elf_relocate_section (bfd *output_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;
|
| + 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;
|
| @@ -1449,24 +2024,42 @@ mn10300_elf_relocate_section (bfd *output_bfd,
|
| 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);
|
| + }
|
| + 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
|
| @@ -1478,6 +2071,10 @@ mn10300_elf_relocate_section (bfd *output_bfd,
|
| && 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))
|
| @@ -1512,9 +2109,9 @@ mn10300_elf_relocate_section (bfd *output_bfd,
|
| 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)
|
| continue;
|
| @@ -1571,6 +2168,9 @@ mn10300_elf_relocate_section (bfd *output_bfd,
|
| 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)
|
| + 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");
|
| @@ -1581,11 +2181,9 @@ mn10300_elf_relocate_section (bfd *output_bfd,
|
| /* 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;
|
| }
|
| }
|
| }
|
| @@ -2581,6 +3179,7 @@ mn10300_elf_relax_section (bfd *abfd,
|
| {
|
| 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;
|
| @@ -2611,6 +3210,25 @@ mn10300_elf_relax_section (bfd *abfd,
|
| 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;
|
| @@ -2766,7 +3384,7 @@ mn10300_elf_relax_section (bfd *abfd,
|
| 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;
|
|
|
| @@ -2862,9 +3480,7 @@ mn10300_elf_relax_section (bfd *abfd,
|
| {
|
| 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)
|
| @@ -3304,9 +3920,7 @@ mn10300_elf_relax_section (bfd *abfd,
|
| {
|
| 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;
|
| @@ -3949,11 +4563,38 @@ elf32_mn10300_link_hash_newfunc (struct bfd_hash_entry *entry,
|
| 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);
|
| +}
|
| +
|
| /* Create an mn10300 ELF linker hash table. */
|
|
|
| static struct bfd_link_hash_table *
|
| @@ -3976,6 +4617,11 @@ elf32_mn10300_link_hash_table_create (bfd *abfd)
|
| }
|
|
|
| ret->flags = 0;
|
| + ret->tls_ldm_got.refcount = 0;
|
| + ret->tls_ldm_got.offset = -1;
|
| + ret->tls_ldm_got.got_allocated = 0;
|
| + ret->tls_ldm_got.rel_emitted = 0;
|
| +
|
| amt = sizeof (struct elf_link_hash_table);
|
| ret->static_hash_table = bfd_malloc (amt);
|
| if (ret->static_hash_table == NULL)
|
| @@ -4154,6 +4800,7 @@ _bfd_mn10300_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
|
| 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)
|
| @@ -4176,10 +4823,11 @@ _bfd_mn10300_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
|
| 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;
|
| @@ -4187,32 +4835,6 @@ _bfd_mn10300_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
|
| 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
|
| @@ -4221,8 +4843,8 @@ _bfd_mn10300_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
|
| 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;
|
|
|
| @@ -4239,10 +4861,10 @@ _bfd_mn10300_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
|
| copy relocs. */
|
| if (! info->shared)
|
| {
|
| - 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;
|
| @@ -4262,10 +4884,11 @@ static bfd_boolean
|
| _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
|
| @@ -4301,7 +4924,7 @@ _bfd_mn10300_elf_adjust_dynamic_symbol (struct bfd_link_info * info,
|
| 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
|
| @@ -4328,12 +4951,12 @@ _bfd_mn10300_elf_adjust_dynamic_symbol (struct bfd_link_info * info,
|
|
|
| /* 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 = bfd_get_linker_section (dynobj, ".rela.plt");
|
| BFD_ASSERT (s != NULL);
|
| s->size += sizeof (Elf32_External_Rela);
|
|
|
| @@ -4367,13 +4990,6 @@ _bfd_mn10300_elf_adjust_dynamic_symbol (struct bfd_link_info * info,
|
| 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
|
| @@ -4384,18 +5000,18 @@ _bfd_mn10300_elf_adjust_dynamic_symbol (struct bfd_link_info * info,
|
| 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;
|
| @@ -4410,13 +5026,14 @@ static bfd_boolean
|
| _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)
|
| @@ -4424,7 +5041,7 @@ _bfd_mn10300_elf_size_dynamic_sections (bfd * output_bfd,
|
| /* Set the contents of the .interp section to the interpreter. */
|
| if (info->executable)
|
| {
|
| - 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;
|
| @@ -4437,11 +5054,18 @@ _bfd_mn10300_elf_size_dynamic_sections (bfd * output_bfd,
|
| 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 = bfd_get_linker_section (dynobj, ".rela.got");
|
| + 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. */
|
| @@ -4580,9 +5204,10 @@ _bfd_mn10300_elf_finish_dynamic_symbol (bfd * output_bfd,
|
| 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)
|
| {
|
| @@ -4598,9 +5223,9 @@ _bfd_mn10300_elf_finish_dynamic_symbol (bfd * output_bfd,
|
|
|
| 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 = bfd_get_linker_section (dynobj, ".rela.plt");
|
| BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
|
|
|
| /* Get the index in the procedure linkage table which
|
| @@ -4677,39 +5302,72 @@ _bfd_mn10300_elf_finish_dynamic_symbol (bfd * output_bfd,
|
| 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 = bfd_get_linker_section (dynobj, ".rela.got");
|
| 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 (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
|
| + {
|
| + 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)
|
| @@ -4722,8 +5380,7 @@ _bfd_mn10300_elf_finish_dynamic_symbol (bfd * output_bfd,
|
| && (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
|
| @@ -4754,12 +5411,12 @@ _bfd_mn10300_elf_finish_dynamic_sections (bfd * output_bfd,
|
| 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)
|
| {
|
| @@ -4824,7 +5481,7 @@ _bfd_mn10300_elf_finish_dynamic_sections (bfd * output_bfd,
|
| }
|
|
|
| /* 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)
|
| @@ -4846,6 +5503,14 @@ _bfd_mn10300_elf_finish_dynamic_sections (bfd * output_bfd,
|
| /* 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;
|
| }
|
| }
|
|
|
| @@ -4887,12 +5552,7 @@ _bfd_mn10300_elf_reloc_type_class (const Elf_Internal_Rela *rela)
|
| 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);
|
| }
|
|
|
| @@ -4948,7 +5608,8 @@ mn10300_elf_mkobject (bfd *abfd)
|
| _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
|
|
|
|
|