/* Xilinx MicroBlaze-specific support for 32-bit ELF
- Copyright 2009 Free Software Foundation, Inc.
+ Copyright (C) 2009-2017 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
int dbg = 0;
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "bfdlink.h"
#include "libbfd.h"
#include "elf-bfd.h"
/* This reloc does nothing. */
HOWTO (R_MICROBLAZE_NONE, /* Type. */
0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 32, /* Bitsize. */
+ 3, /* Size (0 = byte, 1 = short, 2 = long). */
+ 0, /* Bitsize. */
FALSE, /* PC_relative. */
0, /* Bitpos. */
- complain_overflow_bitfield, /* Complain on overflow. */
+ complain_overflow_dont, /* Complain on overflow. */
NULL, /* Special Function. */
"R_MICROBLAZE_NONE", /* Name. */
FALSE, /* Partial Inplace. */
/* This reloc does nothing. Used for relaxation. */
HOWTO (R_MICROBLAZE_64_NONE, /* Type. */
0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 32, /* Bitsize. */
+ 3, /* Size (0 = byte, 1 = short, 2 = long). */
+ 0, /* Bitsize. */
TRUE, /* PC_relative. */
0, /* Bitpos. */
- complain_overflow_bitfield, /* Complain on overflow. */
+ complain_overflow_dont, /* Complain on overflow. */
NULL, /* Special Function. */
"R_MICROBLAZE_64_NONE",/* Name. */
FALSE, /* Partial Inplace. */
0, /* Source Mask. */
0x0000ffff, /* Dest Mask. */
FALSE), /* PC relative offset? */
+
+ /* Marker relocs for TLS. */
+ HOWTO (R_MICROBLAZE_TLS,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MICROBLAZE_TLS", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_MICROBLAZE_TLSGD,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MICROBLAZE_TLSGD", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ HOWTO (R_MICROBLAZE_TLSLD,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MICROBLAZE_TLSLD", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Computes the load module index of the load module that contains the
+ definition of its TLS sym. */
+ HOWTO (R_MICROBLAZE_TLSDTPMOD32,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MICROBLAZE_TLSDTPMOD32", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Computes a dtv-relative displacement, the difference between the value
+ of sym+add and the base address of the thread-local storage block that
+ contains the definition of sym, minus 0x8000. Used for initializing GOT */
+ HOWTO (R_MICROBLAZE_TLSDTPREL32,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MICROBLAZE_TLSDTPREL32", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Computes a dtv-relative displacement, the difference between the value
+ of sym+add and the base address of the thread-local storage block that
+ contains the definition of sym, minus 0x8000. */
+ HOWTO (R_MICROBLAZE_TLSDTPREL64,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MICROBLAZE_TLSDTPREL64", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Computes a tp-relative displacement, the difference between the value of
+ sym+add and the value of the thread pointer (r13). */
+ HOWTO (R_MICROBLAZE_TLSGOTTPREL32,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MICROBLAZE_TLSGOTTPREL32", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Computes a tp-relative displacement, the difference between the value of
+ sym+add and the value of the thread pointer (r13). */
+ HOWTO (R_MICROBLAZE_TLSTPREL32,
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MICROBLAZE_TLSTPREL32", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
};
#ifndef NUM_ELEM
case BFD_RELOC_MICROBLAZE_32_GOTOFF:
microblaze_reloc = R_MICROBLAZE_GOTOFF_32;
break;
+ case BFD_RELOC_MICROBLAZE_64_TLSGD:
+ microblaze_reloc = R_MICROBLAZE_TLSGD;
+ break;
+ case BFD_RELOC_MICROBLAZE_64_TLSLD:
+ microblaze_reloc = R_MICROBLAZE_TLSLD;
+ break;
+ case BFD_RELOC_MICROBLAZE_32_TLSDTPREL:
+ microblaze_reloc = R_MICROBLAZE_TLSDTPREL32;
+ break;
+ case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
+ microblaze_reloc = R_MICROBLAZE_TLSDTPREL64;
+ break;
+ case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD:
+ microblaze_reloc = R_MICROBLAZE_TLSDTPMOD32;
+ break;
+ case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL:
+ microblaze_reloc = R_MICROBLAZE_TLSGOTTPREL32;
+ break;
+ case BFD_RELOC_MICROBLAZE_64_TLSTPREL:
+ microblaze_reloc = R_MICROBLAZE_TLSTPREL32;
+ break;
case BFD_RELOC_MICROBLAZE_COPY:
microblaze_reloc = R_MICROBLAZE_COPY;
break;
arelent * cache_ptr,
Elf_Internal_Rela * dst)
{
+ unsigned int r_type;
+
if (!microblaze_elf_howto_table [R_MICROBLAZE_32])
/* Initialize howto table if needed. */
microblaze_elf_howto_init ();
- BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_MICROBLAZE_max);
+ r_type = ELF32_R_TYPE (dst->r_info);
+ if (r_type >= R_MICROBLAZE_max)
+ {
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B: unrecognised MicroBlaze reloc number: %d"),
+ abfd, r_type);
+ bfd_set_error (bfd_error_bad_value);
+ r_type = R_MICROBLAZE_NONE;
+ }
- cache_ptr->howto = microblaze_elf_howto_table [ELF32_R_TYPE (dst->r_info)];
+ cache_ptr->howto = microblaze_elf_howto_table [r_type];
}
/* Microblaze ELF local labels start with 'L.' or '$L', not '.L'. */
/* Track dynamic relocs copied for this symbol. */
struct elf32_mb_dyn_relocs *dyn_relocs;
+ /* TLS Reference Types for the symbol; Updated by check_relocs */
+#define TLS_GD 1 /* GD reloc. */
+#define TLS_LD 2 /* LD reloc. */
+#define TLS_TPREL 4 /* TPREL reloc, => IE. */
+#define TLS_DTPREL 8 /* DTPREL reloc, => LD. */
+#define TLS_TLS 16 /* Any TLS reloc. */
+ unsigned char tls_mask;
+
};
+#define IS_TLS_GD(x) (x == (TLS_TLS | TLS_GD))
+#define IS_TLS_LD(x) (x == (TLS_TLS | TLS_LD))
+#define IS_TLS_DTPREL(x) (x == (TLS_TLS | TLS_DTPREL))
+#define IS_TLS_NONE(x) (x == 0)
+
#define elf32_mb_hash_entry(ent) ((struct elf32_mb_link_hash_entry *)(ent))
/* ELF linker hash table. */
{
struct elf_link_hash_table elf;
- /* Short-cuts to get to dynamic linker sections. */
- asection *sgot;
- asection *sgotplt;
- asection *srelgot;
- asection *splt;
- asection *srelplt;
- asection *sdynbss;
- asection *srelbss;
-
/* Small local sym to section mapping cache. */
struct sym_cache sym_sec;
+
+ /* TLS Local Dynamic GOT Entry */
+ union {
+ bfd_signed_vma refcount;
+ bfd_vma offset;
+ } tlsld_got;
};
+/* Nonzero if this section has TLS related relocations. */
+#define has_tls_reloc sec_flg0
+
/* Get the ELF linker hash table from a link_info structure. */
#define elf32_mb_hash_table(p) \
- ((struct elf32_mb_link_hash_table *) ((p)->hash))
+ (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
+ == MICROBLAZE_ELF_DATA ? ((struct elf32_mb_link_hash_table *) ((p)->hash)) : NULL)
/* Create an entry in a microblaze ELF linker hash table. */
eh = (struct elf32_mb_link_hash_entry *) entry;
eh->dyn_relocs = NULL;
+ eh->tls_mask = 0;
}
return entry;
return NULL;
if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
- sizeof (struct elf32_mb_link_hash_entry)))
+ sizeof (struct elf32_mb_link_hash_entry),
+ MICROBLAZE_ELF_DATA))
{
free (ret);
return NULL;
+ h->u.def.section->output_offset);
}
+static bfd_vma
+dtprel_base (struct bfd_link_info *info)
+{
+ /* If tls_sec is NULL, we should have signalled an error already. */
+ if (elf_hash_table (info)->tls_sec == NULL)
+ return 0;
+ return elf_hash_table (info)->tls_sec->vma;
+}
+
+/* The size of the thread control block. */
+#define TCB_SIZE 8
+
+/* Output a simple dynamic relocation into SRELOC. */
+
+static void
+microblaze_elf_output_dynamic_relocation (bfd *output_bfd,
+ asection *sreloc,
+ unsigned long reloc_index,
+ unsigned long indx,
+ int r_type,
+ bfd_vma offset,
+ bfd_vma addend)
+{
+
+ Elf_Internal_Rela rel;
+
+ rel.r_info = ELF32_R_INFO (indx, r_type);
+ rel.r_offset = offset;
+ rel.r_addend = addend;
+
+ bfd_elf32_swap_reloca_out (output_bfd, &rel,
+ (sreloc->contents + reloc_index * sizeof (Elf32_External_Rela)));
+}
+
/* This code is taken from elf32-m32r.c
There is some attempt to make this function usable for many architectures,
both USE_REL and USE_RELA ['twould be nice if such a critter existed],
Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
Elf_Internal_Rela *rel, *relend;
+ int endian = (bfd_little_endian (output_bfd)) ? 0 : 2;
/* Assume success. */
bfd_boolean ret = TRUE;
asection *sreloc;
bfd_vma *local_got_offsets;
+ unsigned int tls_type;
if (!microblaze_elf_howto_table[R_MICROBLAZE_max-1])
microblaze_elf_howto_init ();
htab = elf32_mb_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
local_got_offsets = elf_local_got_offsets (input_bfd);
sreloc = elf_section_data (input_section)->sreloc;
h = NULL;
r_type = ELF32_R_TYPE (rel->r_info);
+ tls_type = 0;
+
if (r_type < 0 || r_type >= (int) R_MICROBLAZE_max)
{
- (*_bfd_error_handler) (_("%s: unknown relocation type %d"),
- bfd_get_filename (input_bfd), (int) r_type);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%s: unknown relocation type %d"),
+ bfd_get_filename (input_bfd), (int) r_type);
bfd_set_error (bfd_error_bad_value);
ret = FALSE;
continue;
howto = microblaze_elf_howto_table[r_type];
r_symndx = ELF32_R_SYM (rel->r_info);
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
{
/* This is a relocatable link. We don't have to change
anything, unless the reloc is against a section symbol,
{
/* External symbol. */
bfd_boolean warned ATTRIBUTE_UNUSED;
+ bfd_boolean ignored ATTRIBUTE_UNUSED;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
sym_name = h->root.root.string;
}
/* Sanity check the address. */
- if (offset > bfd_get_section_limit (output_bfd, input_section))
+ if (offset > bfd_get_section_limit (input_bfd, input_section))
{
r = bfd_reloc_outofrange;
goto check_reloc;
/* Only relocate if the symbol is defined. */
if (sec)
{
- name = bfd_get_section_name (abfd, sec);
+ name = bfd_get_section_name (sec->owner, sec);
if (strcmp (name, ".sdata2") == 0
|| strcmp (name, ".sbss2") == 0)
}
else
{
- (*_bfd_error_handler) (_("%s: The target (%s) of an %s relocation is in the wrong section (%s)"),
- bfd_get_filename (input_bfd),
- sym_name,
- microblaze_elf_howto_table[(int) r_type]->name,
- bfd_get_section_name (abfd, sec));
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%s: The target (%s) of an %s relocation "
+ "is in the wrong section (%s)"),
+ bfd_get_filename (input_bfd),
+ sym_name,
+ microblaze_elf_howto_table[(int) r_type]->name,
+ bfd_get_section_name (sec->owner, sec));
/*bfd_set_error (bfd_error_bad_value); ??? why? */
ret = FALSE;
continue;
/* Only relocate if the symbol is defined. */
if (sec)
{
- name = bfd_get_section_name (abfd, sec);
+ name = bfd_get_section_name (sec->owner, sec);
if (strcmp (name, ".sdata") == 0
|| strcmp (name, ".sbss") == 0)
}
else
{
- (*_bfd_error_handler) (_("%s: The target (%s) of an %s relocation is in the wrong section (%s)"),
- bfd_get_filename (input_bfd),
- sym_name,
- microblaze_elf_howto_table[(int) r_type]->name,
- bfd_get_section_name (abfd, sec));
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%s: The target (%s) of an %s relocation "
+ "is in the wrong section (%s)"),
+ bfd_get_filename (input_bfd),
+ sym_name,
+ microblaze_elf_howto_table[(int) r_type]->name,
+ bfd_get_section_name (sec->owner, sec));
/*bfd_set_error (bfd_error_bad_value); ??? why? */
ret = FALSE;
continue;
break; /* Do nothing. */
case (int) R_MICROBLAZE_GOTPC_64:
- relocation = htab->sgotplt->output_section->vma
- + htab->sgotplt->output_offset;
+ relocation = (htab->elf.sgotplt->output_section->vma
+ + htab->elf.sgotplt->output_offset);
relocation -= (input_section->output_section->vma
+ input_section->output_offset
+ offset + INST_WORD_SIZE);
relocation += addend;
bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
- contents + offset + 2);
+ contents + offset + endian);
bfd_put_16 (input_bfd, relocation & 0xffff,
- contents + offset + 2 + INST_WORD_SIZE);
+ contents + offset + endian + INST_WORD_SIZE);
break;
case (int) R_MICROBLAZE_PLT_64:
{
bfd_vma immediate;
- if (htab->splt != NULL && h != NULL
+ if (htab->elf.splt != NULL && h != NULL
&& h->plt.offset != (bfd_vma) -1)
{
- relocation = (htab->splt->output_section->vma
- + htab->splt->output_offset
+ relocation = (htab->elf.splt->output_section->vma
+ + htab->elf.splt->output_offset
+ h->plt.offset);
unresolved_reloc = FALSE;
immediate = relocation - (input_section->output_section->vma
+ input_section->output_offset
+ offset + INST_WORD_SIZE);
bfd_put_16 (input_bfd, (immediate >> 16) & 0xffff,
- contents + offset + 2);
+ contents + offset + endian);
bfd_put_16 (input_bfd, immediate & 0xffff,
- contents + offset + 2 + INST_WORD_SIZE);
+ contents + offset + endian + INST_WORD_SIZE);
}
else
{
+ offset + INST_WORD_SIZE);
immediate = relocation;
bfd_put_16 (input_bfd, (immediate >> 16) & 0xffff,
- contents + offset + 2);
+ contents + offset + endian);
bfd_put_16 (input_bfd, immediate & 0xffff,
- contents + offset + 2 + INST_WORD_SIZE);
+ contents + offset + endian + INST_WORD_SIZE);
}
break;
}
+ case (int) R_MICROBLAZE_TLSGD:
+ tls_type = (TLS_TLS | TLS_GD);
+ goto dogot;
+ case (int) R_MICROBLAZE_TLSLD:
+ tls_type = (TLS_TLS | TLS_LD);
+ /* Fall through. */
+ dogot:
case (int) R_MICROBLAZE_GOT_64:
{
- if (htab->sgot == NULL)
+ bfd_vma *offp;
+ bfd_vma off, off2;
+ unsigned long indx;
+ bfd_vma static_value;
+
+ bfd_boolean need_relocs = FALSE;
+ if (htab->elf.sgot == NULL)
abort ();
- if (h == NULL)
+
+ indx = 0;
+ offp = NULL;
+
+ /* 1. Identify GOT Offset;
+ 2. Compute Static Values
+ 3. Process Module Id, Process Offset
+ 4. Fixup Relocation with GOT offset value. */
+
+ /* 1. Determine GOT Offset to use : TLS_LD, global, local */
+ if (IS_TLS_LD (tls_type))
+ offp = &htab->tlsld_got.offset;
+ else if (h != NULL)
+ {
+ if (htab->elf.sgotplt != NULL
+ && h->got.offset != (bfd_vma) -1)
+ offp = &h->got.offset;
+ else
+ abort ();
+ }
+ else
{
- bfd_vma off;
if (local_got_offsets == NULL)
abort ();
- off = local_got_offsets[r_symndx];
- /* The LSB indicates whether we've already
- created relocation. */
- if (off & 1)
- off &= ~1;
- else
- {
- bfd_put_32 (output_bfd, relocation + addend,
- htab->sgot->contents + off);
+ offp = &local_got_offsets[r_symndx];
+ }
- if (info->shared)
- {
- Elf_Internal_Rela outrel;
- bfd_byte *loc;
- if (htab->srelgot == NULL)
- abort ();
- outrel.r_offset = (htab->sgot->output_section->vma
- + htab->sgot->output_offset
- + off);
- outrel.r_info = ELF32_R_INFO (0, R_MICROBLAZE_REL);
- outrel.r_addend = relocation + addend;
- loc = htab->srelgot->contents;
- loc += htab->srelgot->reloc_count++
- * sizeof (Elf32_External_Rela);
- bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
- }
- local_got_offsets[r_symndx] |= 1;
- }
- relocation = htab->sgot->output_section->vma
- + htab->sgot->output_offset + off
- - htab->sgotplt->output_section->vma
- - htab->sgotplt->output_offset;
- unresolved_reloc = FALSE;
+ if (!offp)
+ abort ();
+
+ off = (*offp) & ~1;
+ off2 = off;
+
+ if (IS_TLS_LD(tls_type) || IS_TLS_GD(tls_type))
+ off2 = off + 4;
+
+ /* Symbol index to use for relocs */
+ if (h != NULL)
+ {
+ bfd_boolean dyn =
+ elf_hash_table (info)->dynamic_sections_created;
+
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
+ bfd_link_pic (info),
+ h)
+ && (!bfd_link_pic (info)
+ || !SYMBOL_REFERENCES_LOCAL (info, h)))
+ indx = h->dynindx;
}
- else
+
+ /* Need to generate relocs ? */
+ if ((bfd_link_pic (info) || indx != 0)
+ && (h == NULL
+ || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ || h->root.type != bfd_link_hash_undefweak))
+ need_relocs = TRUE;
+
+ /* 2. Compute/Emit Static value of r-expression */
+ static_value = relocation + addend;
+
+ /* 3. Process module-id and offset */
+ if (! ((*offp) & 1) )
{
- if (htab->sgotplt != NULL && h != NULL
- && h->got.offset != (bfd_vma) -1)
+ bfd_vma got_offset;
+
+ got_offset = (htab->elf.sgot->output_section->vma
+ + htab->elf.sgot->output_offset
+ + off);
+
+ /* Process module-id */
+ if (IS_TLS_LD(tls_type))
+ {
+ if (! bfd_link_pic (info))
+ bfd_put_32 (output_bfd, 1,
+ htab->elf.sgot->contents + off);
+ else
+ microblaze_elf_output_dynamic_relocation
+ (output_bfd,
+ htab->elf.srelgot,
+ htab->elf.srelgot->reloc_count++,
+ /* symindex= */ 0, R_MICROBLAZE_TLSDTPMOD32,
+ got_offset, 0);
+ }
+ else if (IS_TLS_GD(tls_type))
+ {
+ if (! need_relocs)
+ bfd_put_32 (output_bfd, 1,
+ htab->elf.sgot->contents + off);
+ else
+ microblaze_elf_output_dynamic_relocation
+ (output_bfd,
+ htab->elf.srelgot,
+ htab->elf.srelgot->reloc_count++,
+ /* symindex= */ indx, R_MICROBLAZE_TLSDTPMOD32,
+ got_offset, indx ? 0 : static_value);
+ }
+
+ /* Process Offset */
+ if (htab->elf.srelgot == NULL)
+ abort ();
+
+ got_offset = (htab->elf.sgot->output_section->vma
+ + htab->elf.sgot->output_offset
+ + off2);
+ if (IS_TLS_LD(tls_type))
+ {
+ /* For LD, offset should be 0 */
+ *offp |= 1;
+ bfd_put_32 (output_bfd, 0,
+ htab->elf.sgot->contents + off2);
+ }
+ else if (IS_TLS_GD(tls_type))
{
- bfd_put_32 (output_bfd, relocation + addend,
- htab->sgot->contents + h->got.offset);
- relocation = htab->sgot->output_section->vma
- + htab->sgot->output_offset
- + h->got.offset
- - htab->sgotplt->output_section->vma
- - htab->sgotplt->output_offset;
- unresolved_reloc = FALSE;
+ *offp |= 1;
+ static_value -= dtprel_base(info);
+ if (need_relocs)
+ microblaze_elf_output_dynamic_relocation
+ (output_bfd,
+ htab->elf.srelgot,
+ htab->elf.srelgot->reloc_count++,
+ /* symindex= */ indx, R_MICROBLAZE_TLSDTPREL32,
+ got_offset, indx ? 0 : static_value);
+ else
+ bfd_put_32 (output_bfd, static_value,
+ htab->elf.sgot->contents + off2);
}
else
- abort (); /* ??? */
+ {
+ bfd_put_32 (output_bfd, static_value,
+ htab->elf.sgot->contents + off2);
+
+ /* Relocs for dyn symbols generated by
+ finish_dynamic_symbols */
+ if (bfd_link_pic (info) && h == NULL)
+ {
+ *offp |= 1;
+ microblaze_elf_output_dynamic_relocation
+ (output_bfd,
+ htab->elf.srelgot,
+ htab->elf.srelgot->reloc_count++,
+ /* symindex= */ indx, R_MICROBLAZE_REL,
+ got_offset, static_value);
+ }
+ }
}
+
+ /* 4. Fixup Relocation with GOT offset value
+ Compute relative address of GOT entry for applying
+ the current relocation */
+ relocation = htab->elf.sgot->output_section->vma
+ + htab->elf.sgot->output_offset
+ + off
+ - htab->elf.sgotplt->output_section->vma
+ - htab->elf.sgotplt->output_offset;
+
+ /* Apply Current Relocation */
bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
- contents + offset + 2);
+ contents + offset + endian);
bfd_put_16 (input_bfd, relocation & 0xffff,
- contents + offset + 2 + INST_WORD_SIZE);
+ contents + offset + endian + INST_WORD_SIZE);
+
+ unresolved_reloc = FALSE;
break;
}
bfd_vma immediate;
unsigned short lo, high;
relocation += addend;
- relocation -= htab->sgotplt->output_section->vma
- + htab->sgotplt->output_offset;
+ relocation -= (htab->elf.sgotplt->output_section->vma
+ + htab->elf.sgotplt->output_offset);
/* Write this value into correct location. */
immediate = relocation;
lo = immediate & 0x0000ffff;
high = (immediate >> 16) & 0x0000ffff;
- bfd_put_16 (input_bfd, high, contents + offset + 2);
- bfd_put_16 (input_bfd, lo, contents + offset + INST_WORD_SIZE + 2);
+ bfd_put_16 (input_bfd, high, contents + offset + endian);
+ bfd_put_16 (input_bfd, lo,
+ contents + offset + INST_WORD_SIZE + endian);
break;
}
case (int) R_MICROBLAZE_GOTOFF_32:
{
relocation += addend;
- relocation -= htab->sgotplt->output_section->vma
- + htab->sgotplt->output_offset;
+ relocation -= (htab->elf.sgotplt->output_section->vma
+ + htab->elf.sgotplt->output_offset);
/* Write this value into correct location. */
bfd_put_32 (input_bfd, relocation, contents + offset);
break;
}
+ case (int) R_MICROBLAZE_TLSDTPREL64:
+ relocation += addend;
+ relocation -= dtprel_base(info);
+ bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
+ contents + offset + 2);
+ bfd_put_16 (input_bfd, relocation & 0xffff,
+ contents + offset + 2 + INST_WORD_SIZE);
+ break;
case (int) R_MICROBLAZE_64_PCREL :
case (int) R_MICROBLAZE_64:
case (int) R_MICROBLAZE_32:
{
- /* r_symndx will be zero only for relocs against symbols
+ /* r_symndx will be STN_UNDEF (zero) only for relocs against symbols
from removed linkonce sections, or sections discarded by
a linker script. */
- if (r_symndx == 0 || (input_section->flags & SEC_ALLOC) == 0)
+ if (r_symndx == STN_UNDEF || (input_section->flags & SEC_ALLOC) == 0)
{
relocation += addend;
if (r_type == R_MICROBLAZE_32)
+ input_section->output_offset
+ offset + INST_WORD_SIZE);
bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
- contents + offset + 2);
+ contents + offset + endian);
bfd_put_16 (input_bfd, relocation & 0xffff,
- contents + offset + 2 + INST_WORD_SIZE);
+ contents + offset + endian + INST_WORD_SIZE);
}
break;
}
- if ((info->shared
+ if ((bfd_link_pic (info)
&& (h == NULL
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak)
&& h->dynindx != -1
&& (!info->symbolic
|| !h->def_regular))))
- || (!info->shared
+ || (!bfd_link_pic (info)
&& h != NULL
&& h->dynindx != -1
&& !h->non_got_ref
{
Elf_Internal_Rela outrel;
bfd_byte *loc;
- bfd_boolean skip, relocate = FALSE;
+ bfd_boolean skip;
/* When generating a shared object, these relocations
are copied into the output file to be resolved at run
if (outrel.r_offset == (bfd_vma) -1)
skip = TRUE;
else if (outrel.r_offset == (bfd_vma) -2)
- skip = TRUE, relocate = TRUE;
+ skip = TRUE;
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
else
{
BFD_FAIL ();
- (*_bfd_error_handler)
+ _bfd_error_handler
(_("%B: probably compiled without -fPIC?"),
input_bfd);
bfd_set_error (bfd_error_bad_value);
+ input_section->output_offset
+ offset + INST_WORD_SIZE);
bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
- contents + offset + 2);
+ contents + offset + endian);
bfd_put_16 (input_bfd, relocation & 0xffff,
- contents + offset + 2 + INST_WORD_SIZE);
+ contents + offset + endian + INST_WORD_SIZE);
}
break;
}
switch (r)
{
case bfd_reloc_overflow:
- if (!((*info->callbacks->reloc_overflow)
- (info, (h ? &h->root : NULL), name, howto->name,
- (bfd_vma) 0, input_bfd, input_section, offset)))
- return FALSE;
+ (*info->callbacks->reloc_overflow)
+ (info, (h ? &h->root : NULL), name, howto->name,
+ (bfd_vma) 0, input_bfd, input_section, offset);
break;
case bfd_reloc_undefined:
- if (!((*info->callbacks->undefined_symbol)
- (info, name, input_bfd, input_section, offset, TRUE)))
- return FALSE;
+ (*info->callbacks->undefined_symbol)
+ (info, name, input_bfd, input_section, offset, TRUE);
break;
case bfd_reloc_outofrange:
errmsg = _("internal error: unknown error");
/* Fall through. */
common_error:
- if (!((*info->callbacks->warning)
- (info, errmsg, name, input_bfd, input_section, offset)))
- return FALSE;
+ (*info->callbacks->warning) (info, errmsg, name, input_bfd,
+ input_section, offset);
break;
}
}
/* Calculate fixup value for reference. */
static int
-calc_fixup (bfd_vma addr, asection *sec)
+calc_fixup (bfd_vma start, bfd_vma size, asection *sec)
{
+ bfd_vma end = start + size;
int i, fixup = 0;
if (sec == NULL || sec->relax == NULL)
/* Look for addr in relax table, total fixup value. */
for (i = 0; i < sec->relax_count; i++)
{
- if (addr <= sec->relax[i].addr)
+ if (end <= sec->relax[i].addr)
break;
+ if ((end != start) && (start > sec->relax[i].addr))
+ continue;
fixup += sec->relax[i].size;
}
-
return fixup;
}
+/* Read-modify-write into the bfd, an immediate value into appropriate fields of
+ a 32-bit instruction. */
+static void
+microblaze_bfd_write_imm_value_32 (bfd *abfd, bfd_byte *bfd_addr, bfd_vma val)
+{
+ unsigned long instr = bfd_get_32 (abfd, bfd_addr);
+ instr &= ~0x0000ffff;
+ instr |= (val & 0x0000ffff);
+ bfd_put_32 (abfd, instr, bfd_addr);
+}
+
+/* Read-modify-write into the bfd, an immediate value into appropriate fields of
+ two consecutive 32-bit instructions. */
+static void
+microblaze_bfd_write_imm_value_64 (bfd *abfd, bfd_byte *bfd_addr, bfd_vma val)
+{
+ unsigned long instr_hi;
+ unsigned long instr_lo;
+
+ instr_hi = bfd_get_32 (abfd, bfd_addr);
+ instr_hi &= ~0x0000ffff;
+ instr_hi |= ((val >> 16) & 0x0000ffff);
+ bfd_put_32 (abfd, instr_hi, bfd_addr);
+
+ instr_lo = bfd_get_32 (abfd, bfd_addr + INST_WORD_SIZE);
+ instr_lo &= ~0x0000ffff;
+ instr_lo |= (val & 0x0000ffff);
+ bfd_put_32 (abfd, instr_lo, bfd_addr + INST_WORD_SIZE);
+}
+
static bfd_boolean
microblaze_elf_relax_section (bfd *abfd,
asection *sec,
bfd_byte *free_contents = NULL;
int rel_count;
unsigned int shndx;
- int i, index;
+ int i, sym_index;
asection *o;
struct elf_link_hash_entry *sym_hash;
Elf_Internal_Sym *isymbuf, *isymend;
*again = FALSE;
/* Only do this for a text section. */
- if (link_info->relocatable
+ if (bfd_link_relocatable (link_info)
|| (sec->flags & SEC_RELOC) == 0
- || (sec->reloc_count == 0))
+ || (sec->reloc_count == 0)
+ || (sec->flags & SEC_CODE) == 0)
return TRUE;
BFD_ASSERT ((sec->size > 0) || (sec->rawsize > 0));
0, NULL, NULL, NULL);
BFD_ASSERT (isymbuf != NULL);
- internal_relocs = _bfd_elf_link_read_relocs
- (abfd, sec, NULL, NULL, link_info->keep_memory);
+ internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, link_info->keep_memory);
if (internal_relocs == NULL)
goto error_return;
if (! link_info->keep_memory)
if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
{
/* A local symbol. */
- Elf_Internal_Sym *isym;
asection *sym_sec;
isym = isymbuf + ELF32_R_SYM (irel->r_info);
bfd_vma nraddr;
/* Get the new reloc address. */
- nraddr = irel->r_offset - calc_fixup (irel->r_offset, sec);
+ nraddr = irel->r_offset - calc_fixup (irel->r_offset, 0, sec);
switch ((enum elf_microblaze_reloc_type) ELF32_R_TYPE (irel->r_info))
{
default:
range to be adjusted, and hence must be changed. */
if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
{
- Elf_Internal_Sym *isym;
isym = isymbuf + ELF32_R_SYM (irel->r_info);
/* Only handle relocs against .text. */
if (isym->st_shndx == shndx
&& ELF32_ST_TYPE (isym->st_info) == STT_SECTION)
- irel->r_addend -= calc_fixup (irel->r_addend, sec);
+ irel->r_addend -= calc_fixup (irel->r_addend, 0, sec);
}
break;
case R_MICROBLAZE_NONE:
int sfix, efix;
bfd_vma target_address;
target_address = irel->r_addend + irel->r_offset;
- sfix = calc_fixup (irel->r_offset, sec);
- efix = calc_fixup (target_address, sec);
+ sfix = calc_fixup (irel->r_offset, 0, sec);
+ efix = calc_fixup (target_address, 0, sec);
irel->r_addend -= (efix - sfix);
/* Should use HOWTO. */
- bfd_put_16 (abfd, irel->r_addend, contents + irel->r_offset + 2);
+ microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset,
+ irel->r_addend);
}
break;
case R_MICROBLAZE_64_NONE:
int sfix, efix;
bfd_vma target_address;
target_address = irel->r_addend + irel->r_offset + INST_WORD_SIZE;
- sfix = calc_fixup (irel->r_offset + INST_WORD_SIZE, sec);
- efix = calc_fixup (target_address, sec);
+ sfix = calc_fixup (irel->r_offset + INST_WORD_SIZE, 0, sec);
+ efix = calc_fixup (target_address, 0, sec);
irel->r_addend -= (efix - sfix);
- bfd_put_16 (abfd, irel->r_addend, contents + irel->r_offset
- + INST_WORD_SIZE + 2);
+ microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset
+ + INST_WORD_SIZE, irel->r_addend);
}
break;
}
/* Look through all other sections. */
for (o = abfd->sections; o != NULL; o = o->next)
{
- Elf_Internal_Rela *internal_relocs;
+ Elf_Internal_Rela *irelocs;
Elf_Internal_Rela *irelscan, *irelscanend;
bfd_byte *ocontents;
/* We always cache the relocs. Perhaps, if info->keep_memory is
FALSE, we should free them, if we are permitted to. */
- internal_relocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, TRUE);
- if (internal_relocs == NULL)
+ irelocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, TRUE);
+ if (irelocs == NULL)
goto error_return;
ocontents = NULL;
- irelscanend = internal_relocs + o->reloc_count;
- for (irelscan = internal_relocs; irelscan < irelscanend; irelscan++)
+ irelscanend = irelocs + o->reloc_count;
+ for (irelscan = irelocs; irelscan < irelscanend; irelscan++)
{
if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32)
{
}
}
- irelscan->r_addend -= calc_fixup (irelscan->r_addend, sec);
+ irelscan->r_addend -= calc_fixup (irelscan->r_addend, 0, sec);
}
else if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_SYM_OP_SYM)
{
}
irelscan->r_addend -= calc_fixup (irel->r_addend
+ isym->st_value,
+ 0,
sec);
}
}
}
}
- immediate = (unsigned short) bfd_get_16 (abfd, ocontents +
- irelscan->r_offset + 2);
+ unsigned long instr = bfd_get_32 (abfd, ocontents + irelscan->r_offset);
+ immediate = instr & 0x0000ffff;
target_address = immediate;
- offset = calc_fixup (target_address, sec);
+ offset = calc_fixup (target_address, 0, sec);
immediate -= offset;
irelscan->r_addend -= offset;
- bfd_put_16 (abfd, immediate, ocontents + irelscan->r_offset + 2);
+ microblaze_bfd_write_imm_value_32 (abfd, ocontents + irelscan->r_offset,
+ irelscan->r_addend);
}
}
elf_section_data (o)->this_hdr.contents = ocontents;
}
}
- immediate = (unsigned short) (bfd_get_16 (abfd, ocontents
- + irelscan->r_offset
- + 2) << 16)
- & 0xffff0000;
- immediate += (unsigned short) (bfd_get_16 (abfd, ocontents
- + irelscan->r_offset
- + INST_WORD_SIZE + 2))
- & 0x0000ffff;
-
- offset = calc_fixup (irelscan->r_addend, sec);
+ unsigned long instr_hi = bfd_get_32 (abfd, ocontents
+ + irelscan->r_offset);
+ unsigned long instr_lo = bfd_get_32 (abfd, ocontents
+ + irelscan->r_offset
+ + INST_WORD_SIZE);
+ immediate = (instr_hi & 0x0000ffff) << 16;
+ immediate |= (instr_lo & 0x0000ffff);
+ offset = calc_fixup (irelscan->r_addend, 0, sec);
immediate -= offset;
irelscan->r_addend -= offset;
}
elf_section_data (o)->this_hdr.contents = ocontents;
}
}
-
- immediate = (unsigned short)
- (bfd_get_16 (abfd, ocontents + irelscan->r_offset + 2) << 16)
- & 0xffff0000;
- immediate += (unsigned short)
- (bfd_get_16 (abfd, ocontents + irelscan->r_offset
- + INST_WORD_SIZE + 2))
- & 0x0000ffff;
+ unsigned long instr_hi = bfd_get_32 (abfd, ocontents
+ + irelscan->r_offset);
+ unsigned long instr_lo = bfd_get_32 (abfd, ocontents
+ + irelscan->r_offset
+ + INST_WORD_SIZE);
+ immediate = (instr_hi & 0x0000ffff) << 16;
+ immediate |= (instr_lo & 0x0000ffff);
target_address = immediate;
- offset = calc_fixup (target_address, sec);
+ offset = calc_fixup (target_address, 0, sec);
immediate -= offset;
irelscan->r_addend -= offset;
- bfd_put_16 (abfd, ((immediate >> 16) & 0x0000ffff),
- ocontents + irelscan->r_offset + 2);
- bfd_put_16 (abfd, (immediate & 0x0000ffff),
- ocontents + irelscan->r_offset + INST_WORD_SIZE + 2);
+ microblaze_bfd_write_imm_value_64 (abfd, ocontents
+ + irelscan->r_offset, immediate);
}
}
}
for (isym = isymbuf; isym < isymend; isym++)
{
if (isym->st_shndx == shndx)
- isym->st_value =- calc_fixup (isym->st_value, sec);
+ {
+ isym->st_value -= calc_fixup (isym->st_value, 0, sec);
+ if (isym->st_size)
+ isym->st_size -= calc_fixup (isym->st_value, isym->st_size, sec);
+ }
}
/* Now adjust the global symbols defined in this section. */
isym = isymbuf + symtab_hdr->sh_info;
- isymend = isymbuf + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym));
- for (index = 0; isym < isymend; isym++, index++)
+ symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)) - symtab_hdr->sh_info;
+ for (sym_index = 0; sym_index < symcount; sym_index++)
{
- sym_hash = elf_sym_hashes (abfd)[index];
- if (isym->st_shndx == shndx
- && (sym_hash->root.type == bfd_link_hash_defined
+ sym_hash = elf_sym_hashes (abfd)[sym_index];
+ if ((sym_hash->root.type == bfd_link_hash_defined
|| sym_hash->root.type == bfd_link_hash_defweak)
&& sym_hash->root.u.def.section == sec)
- {
- sym_hash->root.u.def.value -= calc_fixup (sym_hash->root.u.def.value,
- sec);
- }
- }
+ {
+ sym_hash->root.u.def.value -= calc_fixup (sym_hash->root.u.def.value,
+ 0, sec);
+ if (sym_hash->size)
+ sym_hash->size -= calc_fixup (sym_hash->root.u.def.value,
+ sym_hash->size, sec);
+ }
+ }
/* Physically move the code and change the cooked size. */
dest = sec->relax[0].addr;
if (sec->relax_count == 0)
{
+ *again = FALSE;
free (sec->relax);
sec->relax = NULL;
}
+ else
+ *again = TRUE;
return TRUE;
error_return:
static asection *
microblaze_elf_gc_mark_hook (asection *sec,
- struct bfd_link_info * info ATTRIBUTE_UNUSED,
+ struct bfd_link_info * info,
Elf_Internal_Rela * rel,
struct elf_link_hash_entry * h,
Elf_Internal_Sym * sym)
{
if (h != NULL)
- {
- switch (ELF32_R_TYPE (rel->r_info))
- {
- case R_MICROBLAZE_GNU_VTINHERIT:
- case R_MICROBLAZE_GNU_VTENTRY:
- break;
-
- default:
- switch (h->root.type)
- {
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- return h->root.u.def.section;
-
- case bfd_link_hash_common:
- return h->root.u.c.p->section;
-
- default:
- break;
- }
- }
- }
- else
- return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
-
- return NULL;
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ case R_MICROBLAZE_GNU_VTINHERIT:
+ case R_MICROBLAZE_GNU_VTENTRY:
+ return NULL;
+ }
+
+ return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
}
/* Update the got entry reference counts for the section being removed. */
#define PLT_ENTRY_WORD_2 0x98186000 /* "brad r12". */
#define PLT_ENTRY_WORD_3 0x80000000 /* "nop". */
-/* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up
- shortcuts to them in our hash table. */
-
static bfd_boolean
-create_got_section (bfd *dynobj, struct bfd_link_info *info)
+update_local_sym_info (bfd *abfd,
+ Elf_Internal_Shdr *symtab_hdr,
+ unsigned long r_symndx,
+ unsigned int tls_type)
{
- struct elf32_mb_link_hash_table *htab;
+ bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (abfd);
+ unsigned char *local_got_tls_masks;
- if (! _bfd_elf_create_got_section (dynobj, info))
- return FALSE;
- htab = elf32_mb_hash_table (info);
- htab->sgot = bfd_get_section_by_name (dynobj, ".got");
- htab->sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
- if (!htab->sgot || !htab->sgotplt)
- return FALSE;
+ if (local_got_refcounts == NULL)
+ {
+ bfd_size_type size = symtab_hdr->sh_info;
+
+ size *= (sizeof (*local_got_refcounts) + sizeof (*local_got_tls_masks));
+ local_got_refcounts = bfd_zalloc (abfd, size);
+ if (local_got_refcounts == NULL)
+ return FALSE;
+ elf_local_got_refcounts (abfd) = local_got_refcounts;
+ }
+
+ local_got_tls_masks =
+ (unsigned char *) (local_got_refcounts + symtab_hdr->sh_info);
+ local_got_tls_masks[r_symndx] |= tls_type;
+ local_got_refcounts[r_symndx] += 1;
- htab->srelgot = bfd_make_section (dynobj, ".rela.got");
- if (htab->srelgot == NULL
- || ! bfd_set_section_flags (dynobj, htab->srelgot, SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED
- | SEC_READONLY)
- || ! bfd_set_section_alignment (dynobj, htab->srelgot, 2))
- return FALSE;
return TRUE;
}
-
/* Look through the relocs for a section during the first phase. */
static bfd_boolean
const Elf_Internal_Rela * rel;
const Elf_Internal_Rela * rel_end;
struct elf32_mb_link_hash_table *htab;
- bfd_vma *local_got_offsets;
asection *sreloc = NULL;
- if (info->relocatable)
+ if (bfd_link_relocatable (info))
return TRUE;
htab = elf32_mb_hash_table (info);
- local_got_offsets = elf_local_got_offsets (abfd);
+ if (htab == NULL)
+ return FALSE;
+
symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
unsigned int r_type;
struct elf_link_hash_entry * h;
unsigned long r_symndx;
+ unsigned char tls_type = 0;
r_symndx = ELF32_R_SYM (rel->r_info);
r_type = ELF32_R_TYPE (rel->r_info);
if (r_symndx < symtab_hdr->sh_info)
h = NULL;
else
- h = sym_hashes [r_symndx - symtab_hdr->sh_info];
+ {
+ h = sym_hashes [r_symndx - symtab_hdr->sh_info];
+
+ /* PR15323, ref flags aren't set for references in the same
+ object. */
+ h->root.non_ir_ref = 1;
+ }
switch (r_type)
{
break;
/* This relocation requires .got entry. */
+ case R_MICROBLAZE_TLSGD:
+ tls_type |= (TLS_TLS | TLS_GD);
+ goto dogottls;
+ case R_MICROBLAZE_TLSLD:
+ tls_type |= (TLS_TLS | TLS_LD);
+ /* Fall through. */
+ dogottls:
+ sec->has_tls_reloc = 1;
+ /* Fall through. */
+ case R_MICROBLAZE_GOTOFF_64:
case R_MICROBLAZE_GOT_64:
- if (htab->sgot == NULL)
+ if (htab->elf.sgot == NULL)
{
if (htab->elf.dynobj == NULL)
htab->elf.dynobj = abfd;
- if (!create_got_section (htab->elf.dynobj, info))
+ if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
return FALSE;
}
if (h != NULL)
{
h->got.refcount += 1;
+ elf32_mb_hash_entry (h)->tls_mask |= tls_type;
}
else
{
- bfd_signed_vma *local_got_refcounts;
-
- /* This is a global offset table entry for a local symbol. */
- local_got_refcounts = elf_local_got_refcounts (abfd);
- if (local_got_refcounts == NULL)
- {
- bfd_size_type size;
-
- size = symtab_hdr->sh_info;
- size *= sizeof (bfd_signed_vma);
- local_got_refcounts = bfd_zalloc (abfd, size);
- if (local_got_refcounts == NULL)
- return FALSE;
- elf_local_got_refcounts (abfd) = local_got_refcounts;
- }
- local_got_refcounts[r_symndx] += 1;
+ if (! update_local_sym_info(abfd, symtab_hdr, r_symndx, tls_type) )
+ return FALSE;
}
break;
case R_MICROBLAZE_64_PCREL:
case R_MICROBLAZE_32:
{
- if (h != NULL && !info->shared)
+ if (h != NULL && !bfd_link_pic (info))
{
/* we may need a copy reloc. */
h->non_got_ref = 1;
dynamic library if we manage to avoid copy relocs for the
symbol. */
- if ((info->shared
+ if ((bfd_link_pic (info)
&& (sec->flags & SEC_ALLOC) != 0
&& (r_type != R_MICROBLAZE_64_PCREL
|| (h != NULL
&& (! info->symbolic
|| h->root.type == bfd_link_hash_defweak
|| !h->def_regular))))
- || (!info->shared
+ || (!bfd_link_pic (info)
&& (sec->flags & SEC_ALLOC) != 0
&& h != NULL
&& (h->root.type == bfd_link_hash_defweak
if (sreloc == NULL)
{
- const char *name;
bfd *dynobj;
- unsigned int strndx = elf_elfheader (abfd)->e_shstrndx;
- unsigned int shnam = elf_section_data (sec)->rel_hdr.sh_name;
-
- name = bfd_elf_string_from_elf_section (abfd, strndx, shnam);
- if (name == NULL)
- return FALSE;
-
- if (strncmp (name, ".rela", 5) != 0
- || strcmp (bfd_get_section_name (abfd, sec),
- name + 5) != 0)
- {
- (*_bfd_error_handler)
- (_("%B: bad relocation section name `%s\'"),
- abfd, name);
- }
if (htab->elf.dynobj == NULL)
htab->elf.dynobj = abfd;
dynobj = htab->elf.dynobj;
- sreloc = bfd_get_section_by_name (dynobj, name);
+ sreloc = _bfd_elf_make_dynamic_reloc_section (sec, dynobj,
+ 2, abfd, 1);
if (sreloc == NULL)
- {
- flagword flags;
-
- sreloc = bfd_make_section (dynobj, name);
- flags = (SEC_HAS_CONTENTS | SEC_READONLY
- | SEC_IN_MEMORY | SEC_LINKER_CREATED);
- if ((sec->flags & SEC_ALLOC) != 0)
- flags |= SEC_ALLOC | SEC_LOAD;
- if (sreloc == NULL
- || ! bfd_set_section_flags (dynobj, sreloc, flags)
- || ! bfd_set_section_alignment (dynobj, sreloc, 2))
- return FALSE;
- }
- elf_section_data (sec)->sreloc = sreloc;
+ return FALSE;
}
/* If this is a global symbol, we count the number of
asection *s;
Elf_Internal_Sym *isym;
+ void *vpp;
isym = bfd_sym_from_r_symndx (&htab->sym_sec,
abfd, r_symndx);
if (s == NULL)
return FALSE;
- head = ((struct elf32_mb_dyn_relocs **)
- &elf_section_data (s)->local_dynrel);
+ vpp = &elf_section_data (s)->local_dynrel;
+ head = (struct elf32_mb_dyn_relocs **) vpp;
}
p = *head;
return TRUE;
}
-static bfd_boolean
-microblaze_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
-{
- struct elf32_mb_link_hash_table *htab;
-
- htab = elf32_mb_hash_table (info);
- if (!htab->sgot && !create_got_section (dynobj, info))
- return FALSE;
-
- if (!_bfd_elf_create_dynamic_sections (dynobj, info))
- return FALSE;
-
- htab->splt = bfd_get_section_by_name (dynobj, ".plt");
- htab->srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
- htab->sdynbss = bfd_get_section_by_name (dynobj, ".dynbss");
- if (!info->shared)
- htab->srelbss = bfd_get_section_by_name (dynobj, ".rela.bss");
-
- if (!htab->splt || !htab->srelplt || !htab->sdynbss
- || (!info->shared && !htab->srelbss))
- abort ();
-
- return TRUE;
-}
-
/* Copy the extra info we tack onto an elf_link_hash_entry. */
static void
eind->dyn_relocs = NULL;
}
+ edir->tls_mask |= eind->tls_mask;
+
_bfd_elf_link_hash_copy_indirect (info, dir, ind);
}
struct elf32_mb_link_hash_table *htab;
struct elf32_mb_link_hash_entry * eh;
struct elf32_mb_dyn_relocs *p;
- asection *sdynbss, *s;
+ asection *s, *srel;
unsigned int power_of_two;
- bfd *dynobj;
htab = elf32_mb_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
/* If this is a function, put it in the procedure linkage table. We
will fill in the contents of the procedure linkage table later,
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
/* We must generate a R_MICROBLAZE_COPY reloc to tell the dynamic linker
to copy the initial value out of the dynamic object and into the
runtime process image. */
- dynobj = elf_hash_table (info)->dynobj;
- BFD_ASSERT (dynobj != NULL);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
{
- htab->srelbss->size += sizeof (Elf32_External_Rela);
+ srel->size += sizeof (Elf32_External_Rela);
h->needs_copy = 1;
}
if (power_of_two > 3)
power_of_two = 3;
- sdynbss = htab->sdynbss;
/* Apply the required alignment. */
- sdynbss->size = BFD_ALIGN (sdynbss->size, (bfd_size_type) (1 << power_of_two));
- if (power_of_two > bfd_get_section_alignment (dynobj, sdynbss))
+ s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
+ if (power_of_two > s->alignment_power)
{
- if (! bfd_set_section_alignment (dynobj, sdynbss, power_of_two))
+ if (!bfd_set_section_alignment (s->owner, s, power_of_two))
return FALSE;
}
/* Define the symbol as being at this point in the section. */
- h->root.u.def.section = sdynbss;
- h->root.u.def.value = sdynbss->size;
+ h->root.u.def.section = s;
+ h->root.u.def.value = s->size;
/* Increment the section size to make room for the symbol. */
- sdynbss->size += h->size;
+ s->size += h->size;
return TRUE;
}
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
- if (h->root.type == bfd_link_hash_warning)
- /* When warning symbols are created, they **replace** the "real"
- entry in the hash table, thus we never get to see the real
- symbol in a hash traversal. So look at it now. */
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
info = (struct bfd_link_info *) dat;
htab = elf32_mb_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
if (htab->elf.dynamic_sections_created
&& h->plt.refcount > 0)
return FALSE;
}
- if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info->shared, h))
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
{
- asection *s = htab->splt;
+ asection *s = htab->elf.splt;
/* The first entry in .plt is reserved. */
if (s->size == 0)
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. */
- htab->sgotplt->size += 4;
+ htab->elf.sgotplt->size += 4;
/* We also need to make an entry in the .rel.plt section. */
- htab->srelplt->size += sizeof (Elf32_External_Rela);
+ htab->elf.srelplt->size += sizeof (Elf32_External_Rela);
}
else
{
h->needs_plt = 0;
}
+ eh = (struct elf32_mb_link_hash_entry *) h;
if (h->got.refcount > 0)
{
+ unsigned int need;
asection *s;
/* Make sure this symbol is output as a dynamic symbol.
return FALSE;
}
- s = htab->sgot;
- h->got.offset = s->size;
- s->size += 4;
- htab->srelgot->size += sizeof (Elf32_External_Rela);
+ need = 0;
+ if ((eh->tls_mask & TLS_TLS) != 0)
+ {
+ /* Handle TLS Symbol */
+ if ((eh->tls_mask & TLS_LD) != 0)
+ {
+ if (!eh->elf.def_dynamic)
+ /* We'll just use htab->tlsld_got.offset. This should
+ always be the case. It's a little odd if we have
+ a local dynamic reloc against a non-local symbol. */
+ htab->tlsld_got.refcount += 1;
+ else
+ need += 8;
+ }
+ if ((eh->tls_mask & TLS_GD) != 0)
+ need += 8;
+ }
+ else
+ {
+ /* Regular (non-TLS) symbol */
+ need += 4;
+ }
+ if (need == 0)
+ {
+ h->got.offset = (bfd_vma) -1;
+ }
+ else
+ {
+ s = htab->elf.sgot;
+ h->got.offset = s->size;
+ s->size += need;
+ htab->elf.srelgot->size += need * (sizeof (Elf32_External_Rela) / 4);
+ }
}
else
h->got.offset = (bfd_vma) -1;
- eh = (struct elf32_mb_link_hash_entry *) h;
if (eh->dyn_relocs == NULL)
return TRUE;
space for pc-relative relocs that have become local due to symbol
visibility changes. */
- if (info->shared)
+ if (bfd_link_pic (info))
{
if (h->def_regular
&& (h->forced_local
bfd *ibfd;
htab = elf32_mb_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
dynobj = htab->elf.dynobj;
BFD_ASSERT (dynobj != NULL);
/* Set up .got offsets for local syms, and space for local dynamic
relocs. */
- for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
{
bfd_signed_vma *local_got;
bfd_signed_vma *end_local_got;
bfd_size_type locsymcount;
Elf_Internal_Shdr *symtab_hdr;
+ unsigned char *lgot_masks;
asection *srel;
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
locsymcount = symtab_hdr->sh_info;
end_local_got = local_got + locsymcount;
- s = htab->sgot;
- srel = htab->srelgot;
+ lgot_masks = (unsigned char *) end_local_got;
+ s = htab->elf.sgot;
+ srel = htab->elf.srelgot;
- for (; local_got < end_local_got; ++local_got)
- {
- if (*local_got > 0)
- {
- *local_got = s->size;
- s->size += 4;
- if (info->shared)
- srel->size += sizeof (Elf32_External_Rela);
+ for (; local_got < end_local_got; ++local_got, ++lgot_masks)
+ {
+ if (*local_got > 0)
+ {
+ unsigned int need = 0;
+ if ((*lgot_masks & TLS_TLS) != 0)
+ {
+ if ((*lgot_masks & TLS_GD) != 0)
+ need += 8;
+ if ((*lgot_masks & TLS_LD) != 0)
+ htab->tlsld_got.refcount += 1;
+ }
+ else
+ need += 4;
+
+ if (need == 0)
+ {
+ *local_got = (bfd_vma) -1;
+ }
+ else
+ {
+ *local_got = s->size;
+ s->size += need;
+ if (bfd_link_pic (info))
+ srel->size += need * (sizeof (Elf32_External_Rela) / 4);
+ }
}
else
*local_got = (bfd_vma) -1;
sym dynamic relocs. */
elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
+ if (htab->tlsld_got.refcount > 0)
+ {
+ htab->tlsld_got.offset = htab->elf.sgot->size;
+ htab->elf.sgot->size += 8;
+ if (bfd_link_pic (info))
+ htab->elf.srelgot->size += sizeof (Elf32_External_Rela);
+ }
+ else
+ htab->tlsld_got.offset = (bfd_vma) -1;
+
if (elf_hash_table (info)->dynamic_sections_created)
{
/* Make space for the trailing nop in .plt. */
- if (htab->splt->size > 0)
- htab->splt->size += 4;
+ if (htab->elf.splt->size > 0)
+ htab->elf.splt->size += 4;
}
/* The check_relocs and adjust_dynamic_symbol entry points have
s->reloc_count = 0;
}
}
- else if (s != htab->splt && s != htab->sgot && s != htab->sgotplt)
+ else if (s != htab->elf.splt
+ && s != htab->elf.sgot
+ && s != htab->elf.sgotplt
+ && s != htab->elf.sdynbss
+ && s != htab->elf.sdynrelro)
{
/* It's not one of our sections, so don't allocate space. */
continue;
#define add_dynamic_entry(TAG, VAL) \
_bfd_elf_add_dynamic_entry (info, TAG, VAL)
- if (info->executable)
+ if (bfd_link_executable (info))
{
if (!add_dynamic_entry (DT_DEBUG, 0))
return FALSE;
|| !add_dynamic_entry (DT_RELAENT, sizeof (Elf32_External_Rela)))
return FALSE;
- if (htab->splt->size != 0)
+ if (htab->elf.splt->size != 0)
{
if (!add_dynamic_entry (DT_PLTGOT, 0)
|| !add_dynamic_entry (DT_PLTRELSZ, 0)
struct elf_link_hash_entry *h,
Elf_Internal_Sym *sym)
{
- bfd *dynobj;
struct elf32_mb_link_hash_table *htab;
+ struct elf32_mb_link_hash_entry *eh = elf32_mb_hash_entry(h);
htab = elf32_mb_hash_table (info);
- dynobj = htab->elf.dynobj;
+ if (htab == NULL)
+ return FALSE;
if (h->plt.offset != (bfd_vma) -1)
{
it up. */
BFD_ASSERT (h->dynindx != -1);
- splt = htab->splt;
- srela = htab->srelplt;
- sgotplt = htab->sgotplt;
+ splt = htab->elf.splt;
+ srela = htab->elf.srelplt;
+ sgotplt = htab->elf.sgotplt;
BFD_ASSERT (splt != NULL && srela != NULL && sgotplt != NULL);
plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; /* first entry reserved. */
got_addr = got_offset;
/* For non-PIC objects we need absolute address of the GOT entry. */
- if (!info->shared)
- got_addr += htab->sgotplt->output_section->vma + sgotplt->output_offset;
+ if (!bfd_link_pic (info))
+ got_addr += sgotplt->output_section->vma + sgotplt->output_offset;
/* Fill in the entry in the procedure linkage table. */
bfd_put_32 (output_bfd, PLT_ENTRY_WORD_0 + ((got_addr >> 16) & 0xffff),
splt->contents + h->plt.offset);
- if (info->shared)
+ if (bfd_link_pic (info))
bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1 + (got_addr & 0xffff),
splt->contents + h->plt.offset + 4);
else
}
}
- if (h->got.offset != (bfd_vma) -1)
+ /* h->got.refcount to be checked ? */
+ if (h->got.offset != (bfd_vma) -1 &&
+ ! ((h->got.offset & 1) ||
+ IS_TLS_LD(eh->tls_mask) || IS_TLS_GD(eh->tls_mask)))
{
asection *sgot;
asection *srela;
- Elf_Internal_Rela rela;
- bfd_byte *loc;
+ bfd_vma offset;
/* This symbol has an entry in the global offset table. Set it
up. */
- sgot = htab->sgot;
- srela = htab->srelgot;
+ sgot = htab->elf.sgot;
+ srela = htab->elf.srelgot;
BFD_ASSERT (sgot != NULL && srela != NULL);
- rela.r_offset = (sgot->output_section->vma
- + sgot->output_offset
- + (h->got.offset &~ (bfd_vma) 1));
+ offset = (sgot->output_section->vma + sgot->output_offset
+ + (h->got.offset &~ (bfd_vma) 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)
+ if (bfd_link_pic (info)
+ && ((info->symbolic && h->def_regular)
+ || h->dynindx == -1))
{
asection *sec = h->root.u.def.section;
- rela.r_info = ELF32_R_INFO (0, R_MICROBLAZE_REL);
- rela.r_addend = (h->root.u.def.value
- + sec->output_section->vma
- + sec->output_offset);
+ bfd_vma value;
+
+ value = h->root.u.def.value;
+ if (sec->output_section != NULL)
+ /* PR 21180: If the output section is NULL, then the symbol is no
+ longer needed, and in theory the GOT entry is redundant. But
+ it is too late to change our minds now... */
+ value += sec->output_section->vma + sec->output_offset;
+
+ microblaze_elf_output_dynamic_relocation (output_bfd,
+ srela, srela->reloc_count++,
+ /* symindex= */ 0,
+ R_MICROBLAZE_REL, offset,
+ value);
}
else
{
- rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_GLOB_DAT);
- rela.r_addend = 0;
+ microblaze_elf_output_dynamic_relocation (output_bfd,
+ srela, srela->reloc_count++,
+ h->dynindx,
+ R_MICROBLAZE_GLOB_DAT,
+ offset, 0);
}
bfd_put_32 (output_bfd, (bfd_vma) 0,
sgot->contents + (h->got.offset &~ (bfd_vma) 1));
- loc = srela->contents;
- loc += srela->reloc_count++ * sizeof (Elf32_External_Rela);
- bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
}
if (h->needs_copy)
BFD_ASSERT (h->dynindx != -1);
- s = bfd_get_section_by_name (h->root.u.def.section->owner,
- ".rela.bss");
- BFD_ASSERT (s != NULL);
-
rela.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_COPY);
rela.r_addend = 0;
+ if (h->root.u.def.section == htab->elf.sdynrelro)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
}
/* Mark some specially defined symbols as absolute. */
- if (strcmp (h->root.root.string, "_DYNAMIC") == 0
- || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
- || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
+ if (h == htab->elf.hdynamic
+ || h == htab->elf.hgot
+ || h == htab->elf.hplt)
sym->st_shndx = SHN_ABS;
return TRUE;
struct elf32_mb_link_hash_table *htab;
htab = elf32_mb_hash_table (info);
+ if (htab == NULL)
+ return FALSE;
+
dynobj = htab->elf.dynobj;
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+ sdyn = bfd_get_linker_section (dynobj, ".dynamic");
if (htab->elf.dynamic_sections_created)
{
asection *splt;
Elf32_External_Dyn *dyncon, *dynconend;
- splt = bfd_get_section_by_name (dynobj, ".plt");
- BFD_ASSERT (splt != NULL && sdyn != NULL);
-
dyncon = (Elf32_External_Dyn *) sdyn->contents;
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size);
for (; dyncon < dynconend; dyncon++)
{
Elf_Internal_Dyn dyn;
- const char *name;
+ asection *s;
bfd_boolean size;
bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
switch (dyn.d_tag)
{
- case DT_PLTGOT: name = ".got.plt"; size = FALSE; break;
- case DT_PLTRELSZ: name = ".rela.plt"; size = TRUE; break;
- case DT_JMPREL: name = ".rela.plt"; size = FALSE; break;
- case DT_RELA: name = ".rela.dyn"; size = FALSE; break;
- case DT_RELASZ: name = ".rela.dyn"; size = TRUE; break;
- default: name = NULL; size = FALSE; break;
- }
+ case DT_PLTGOT:
+ s = htab->elf.sgotplt;
+ size = FALSE;
+ break;
- if (name != NULL)
- {
- asection *s;
+ case DT_PLTRELSZ:
+ s = htab->elf.srelplt;
+ size = TRUE;
+ break;
- s = bfd_get_section_by_name (output_bfd, name);
- if (s == NULL)
- dyn.d_un.d_val = 0;
- else
- {
- if (! size)
- dyn.d_un.d_ptr = s->vma;
- else
- dyn.d_un.d_val = s->size;
- }
- bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ case DT_JMPREL:
+ s = htab->elf.srelplt;
+ size = FALSE;
+ break;
+
+ default:
+ continue;
}
+
+ if (s == NULL)
+ dyn.d_un.d_val = 0;
+ else
+ {
+ if (!size)
+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
+ else
+ dyn.d_un.d_val = s->size;
+ }
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
}
+ splt = htab->elf.splt;
+ BFD_ASSERT (splt != NULL && sdyn != NULL);
+
/* Clear the first entry in the procedure linkage table,
and put a nop in the last four bytes. */
if (splt->size > 0)
/* Set the first entry in the global offset table to the address of
the dynamic section. */
- sgot = bfd_get_section_by_name (dynobj, ".got.plt");
+ sgot = htab->elf.sgotplt;
if (sgot && sgot->size > 0)
{
if (sdyn == NULL)
elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
}
- if (htab->sgot && htab->sgot->size > 0)
- elf_section_data (htab->sgot->output_section)->this_hdr.sh_entsize = 4;
+ if (htab->elf.sgot && htab->elf.sgot->size > 0)
+ elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
return TRUE;
}
bfd_vma *valp)
{
if (sym->st_shndx == SHN_COMMON
- && !info->relocatable
+ && !bfd_link_relocatable (info)
&& sym->st_size <= elf_gp_size (abfd))
{
/* Common symbols less than or equal to -G nn bytes are automatically
put into .sbss. */
- *secp = bfd_make_section_anyway (abfd, ".sbss");
+ *secp = bfd_make_section_old_way (abfd, ".sbss");
if (*secp == NULL
|| ! bfd_set_section_flags (abfd, *secp, SEC_IS_COMMON))
return FALSE;
return TRUE;
}
+#define TARGET_LITTLE_SYM microblaze_elf32_le_vec
+#define TARGET_LITTLE_NAME "elf32-microblazeel"
-#define TARGET_BIG_SYM bfd_elf32_microblaze_vec
+#define TARGET_BIG_SYM microblaze_elf32_vec
#define TARGET_BIG_NAME "elf32-microblaze"
#define ELF_ARCH bfd_arch_microblaze
+#define ELF_TARGET_ID MICROBLAZE_ELF_DATA
#define ELF_MACHINE_CODE EM_MICROBLAZE
#define ELF_MACHINE_ALT1 EM_MICROBLAZE_OLD
-#define ELF_MAXPAGESIZE 0x4 /* 4k, if we ever have 'em. */
+#define ELF_MAXPAGESIZE 0x1000
#define elf_info_to_howto microblaze_elf_info_to_howto
#define elf_info_to_howto_rel NULL
#define bfd_elf32_bfd_is_local_label_name microblaze_elf_is_local_label_name
#define elf_backend_relocate_section microblaze_elf_relocate_section
#define bfd_elf32_bfd_relax_section microblaze_elf_relax_section
+#define bfd_elf32_bfd_merge_private_bfd_data _bfd_generic_verify_endian_match
#define bfd_elf32_bfd_reloc_name_lookup microblaze_elf_reloc_name_lookup
#define elf_backend_gc_mark_hook microblaze_elf_gc_mark_hook
#define elf_backend_want_got_plt 1
#define elf_backend_plt_readonly 1
#define elf_backend_got_header_size 12
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
+#define elf_backend_dtrel_excludes_plt 1
#define elf_backend_adjust_dynamic_symbol microblaze_elf_adjust_dynamic_symbol
-#define elf_backend_create_dynamic_sections microblaze_elf_create_dynamic_sections
+#define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
#define elf_backend_finish_dynamic_sections microblaze_elf_finish_dynamic_sections
#define elf_backend_finish_dynamic_symbol microblaze_elf_finish_dynamic_symbol
#define elf_backend_size_dynamic_sections microblaze_elf_size_dynamic_sections