Microblaze: Add support for handling TLS symbol suffixes and generating
TLS relocs for General Dynamic and Local Dynamic models. bfd/Changelog * reloc.c: Add new relocations * bfd-in2.h: Regenerated * libbfd.h: Regenerated * elf32-microblaze.c (microblaze_elf_howto_raw): Add TLS relocations (microblaze_elf_reloc_type_lookup): Likewise (elf32_mb_link_hash_entry): define TLS reference types (elf32_mb_link_hash_table): add TLS Local dynamic GOT entry #define has_tls_reloc if section has TLS relocs (dtprel_base), (check_unique_offset): New (microblaze_elf_output_dynamic_relocation): output simple dynamic relocation into SRELOC. (microblaze_elf_relocate_section): Accommodate TLS relocations. (microblaze_elf_check_relocs): Likewise (update_local_sym_info): New (microblaze_elf_copy_indirect_symbol): Add tls_mask. (allocate_dynrelocs): Handle TLS symbol (microblaze_elf_size_dynamic_sections): Set size and offset (microblaze_elf_finish_dynamic_symbol): Use microblaze_elf_output_dynamic_relocation gas/Changelog * config/tc-microblaze.c: Define TLS offsets (md_relax_table): Add TLS offsets (imm_types), (match_imm), (get_imm_otype): New to support TLS offsets. (tc_microblaze_fix_adjustable): Add TLS relocs. (md_convert_frag): Support TLS offsets. (md_apply_fix), (md_estimate_size_before_relax), (tc_gen_reloc): Add TLS relocs include/Changelog * elf/microblaze.h: Add TLS relocs to START_RELOC_NUMBERS
This commit is contained in:
parent
3e3420f6a1
commit
69b06cc85f
@ -1,3 +1,25 @@
|
|||||||
|
2012-12-10 Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||||
|
|
||||||
|
* reloc.c (MICROBLAZE): Document new relocations
|
||||||
|
* bfd-in2.h: Regenerated
|
||||||
|
* libbfd.h: Regenerated
|
||||||
|
* elf32-microblaze.c (microblaze_elf_howto_raw): Add TLS relocations
|
||||||
|
(microblaze_elf_reloc_type_lookup): Likewise
|
||||||
|
(elf32_mb_link_hash_entry): define TLS reference types
|
||||||
|
(elf32_mb_link_hash_table): add TLS Local dynamic GOT entry
|
||||||
|
#define has_tls_reloc if section has TLS relocs
|
||||||
|
(dtprel_base), (check_unique_offset): New
|
||||||
|
(microblaze_elf_output_dynamic_relocation): output simple
|
||||||
|
dynamic relocation into SRELOC.
|
||||||
|
(microblaze_elf_relocate_section): Accommodate TLS relocations.
|
||||||
|
(microblaze_elf_check_relocs): Likewise
|
||||||
|
(update_local_sym_info): New
|
||||||
|
(microblaze_elf_copy_indirect_symbol): Add tls_mask.
|
||||||
|
(allocate_dynrelocs): Handle TLS symbol
|
||||||
|
(microblaze_elf_size_dynamic_sections): Set size and offset
|
||||||
|
(microblaze_elf_finish_dynamic_symbol): Use
|
||||||
|
microblaze_elf_output_dynamic_relocation
|
||||||
|
|
||||||
2012-12-09 H.J. Lu <hongjiu.lu@intel.com>
|
2012-12-09 H.J. Lu <hongjiu.lu@intel.com>
|
||||||
|
|
||||||
PR binutils/14933
|
PR binutils/14933
|
||||||
|
@ -5071,6 +5071,37 @@ value in a word. The relocation is relative offset from */
|
|||||||
the dynamic object into the runtime process image. */
|
the dynamic object into the runtime process image. */
|
||||||
BFD_RELOC_MICROBLAZE_COPY,
|
BFD_RELOC_MICROBLAZE_COPY,
|
||||||
|
|
||||||
|
/* Unused Reloc */
|
||||||
|
BFD_RELOC_MICROBLAZE_64_TLS,
|
||||||
|
|
||||||
|
/* This is a 64 bit reloc that stores the 32 bit GOT relative value
|
||||||
|
of the GOT TLS GD info entry in two words (with an imm instruction). The
|
||||||
|
relocation is GOT offset. */
|
||||||
|
BFD_RELOC_MICROBLAZE_64_TLSGD,
|
||||||
|
|
||||||
|
/* This is a 64 bit reloc that stores the 32 bit GOT relative value
|
||||||
|
of the GOT TLS LD info entry in two words (with an imm instruction). The
|
||||||
|
relocation is GOT offset. */
|
||||||
|
BFD_RELOC_MICROBLAZE_64_TLSLD,
|
||||||
|
|
||||||
|
/* This is a 32 bit reloc that stores the Module ID to GOT(n). */
|
||||||
|
BFD_RELOC_MICROBLAZE_32_TLSDTPMOD,
|
||||||
|
|
||||||
|
/* This is a 32 bit reloc that stores TLS offset to GOT(n+1). */
|
||||||
|
BFD_RELOC_MICROBLAZE_32_TLSDTPREL,
|
||||||
|
|
||||||
|
/* This is a 32 bit reloc for storing TLS offset to two words (uses imm
|
||||||
|
instruction) */
|
||||||
|
BFD_RELOC_MICROBLAZE_64_TLSDTPREL,
|
||||||
|
|
||||||
|
/* This is a 64 bit reloc that stores 32-bit thread pointer relative offset
|
||||||
|
to two words (uses imm instruction). */
|
||||||
|
BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL,
|
||||||
|
|
||||||
|
/* This is a 64 bit reloc that stores 32-bit thread pointer relative offset
|
||||||
|
to two words (uses imm instruction). */
|
||||||
|
BFD_RELOC_MICROBLAZE_64_TLSTPREL,
|
||||||
|
|
||||||
/* AArch64 ADD immediate instruction, holding bits 0 to 11 of the address.
|
/* AArch64 ADD immediate instruction, holding bits 0 to 11 of the address.
|
||||||
Used in conjunction with BFD_RELOC_AARCH64_ADR_HI21_PCREL. */
|
Used in conjunction with BFD_RELOC_AARCH64_ADR_HI21_PCREL. */
|
||||||
BFD_RELOC_AARCH64_ADD_LO12,
|
BFD_RELOC_AARCH64_ADD_LO12,
|
||||||
|
@ -370,6 +370,132 @@ static reloc_howto_type microblaze_elf_howto_raw[] =
|
|||||||
0, /* Source Mask. */
|
0, /* Source Mask. */
|
||||||
0x0000ffff, /* Dest Mask. */
|
0x0000ffff, /* Dest Mask. */
|
||||||
FALSE), /* PC relative offset? */
|
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
|
#ifndef NUM_ELEM
|
||||||
@ -461,6 +587,27 @@ microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
|
|||||||
case BFD_RELOC_MICROBLAZE_32_GOTOFF:
|
case BFD_RELOC_MICROBLAZE_32_GOTOFF:
|
||||||
microblaze_reloc = R_MICROBLAZE_GOTOFF_32;
|
microblaze_reloc = R_MICROBLAZE_GOTOFF_32;
|
||||||
break;
|
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:
|
case BFD_RELOC_MICROBLAZE_COPY:
|
||||||
microblaze_reloc = R_MICROBLAZE_COPY;
|
microblaze_reloc = R_MICROBLAZE_COPY;
|
||||||
break;
|
break;
|
||||||
@ -550,8 +697,21 @@ struct elf32_mb_link_hash_entry
|
|||||||
/* Track dynamic relocs copied for this symbol. */
|
/* Track dynamic relocs copied for this symbol. */
|
||||||
struct elf32_mb_dyn_relocs *dyn_relocs;
|
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))
|
#define elf32_mb_hash_entry(ent) ((struct elf32_mb_link_hash_entry *)(ent))
|
||||||
|
|
||||||
/* ELF linker hash table. */
|
/* ELF linker hash table. */
|
||||||
@ -571,8 +731,17 @@ struct elf32_mb_link_hash_table
|
|||||||
|
|
||||||
/* Small local sym to section mapping cache. */
|
/* Small local sym to section mapping cache. */
|
||||||
struct sym_cache sym_sec;
|
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. */
|
/* Get the ELF linker hash table from a link_info structure. */
|
||||||
|
|
||||||
#define elf32_mb_hash_table(p) \
|
#define elf32_mb_hash_table(p) \
|
||||||
@ -604,6 +773,7 @@ link_hash_newfunc (struct bfd_hash_entry *entry,
|
|||||||
|
|
||||||
eh = (struct elf32_mb_link_hash_entry *) entry;
|
eh = (struct elf32_mb_link_hash_entry *) entry;
|
||||||
eh->dyn_relocs = NULL;
|
eh->dyn_relocs = NULL;
|
||||||
|
eh->tls_mask = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
@ -654,6 +824,40 @@ microblaze_elf_final_sdp (struct bfd_link_info *info)
|
|||||||
+ h->u.def.section->output_offset);
|
+ 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
|
/* This code is taken from elf32-m32r.c
|
||||||
There is some attempt to make this function usable for many architectures,
|
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],
|
both USE_REL and USE_RELA ['twould be nice if such a critter existed],
|
||||||
@ -707,6 +911,7 @@ microblaze_elf_relocate_section (bfd *output_bfd,
|
|||||||
bfd_boolean ret = TRUE;
|
bfd_boolean ret = TRUE;
|
||||||
asection *sreloc;
|
asection *sreloc;
|
||||||
bfd_vma *local_got_offsets;
|
bfd_vma *local_got_offsets;
|
||||||
|
unsigned int tls_type;
|
||||||
|
|
||||||
if (!microblaze_elf_howto_table[R_MICROBLAZE_max-1])
|
if (!microblaze_elf_howto_table[R_MICROBLAZE_max-1])
|
||||||
microblaze_elf_howto_init ();
|
microblaze_elf_howto_init ();
|
||||||
@ -738,6 +943,8 @@ microblaze_elf_relocate_section (bfd *output_bfd,
|
|||||||
|
|
||||||
h = NULL;
|
h = NULL;
|
||||||
r_type = ELF32_R_TYPE (rel->r_info);
|
r_type = ELF32_R_TYPE (rel->r_info);
|
||||||
|
tls_type = 0;
|
||||||
|
|
||||||
if (r_type < 0 || r_type >= (int) R_MICROBLAZE_max)
|
if (r_type < 0 || r_type >= (int) R_MICROBLAZE_max)
|
||||||
{
|
{
|
||||||
(*_bfd_error_handler) (_("%s: unknown relocation type %d"),
|
(*_bfd_error_handler) (_("%s: unknown relocation type %d"),
|
||||||
@ -971,70 +1178,182 @@ microblaze_elf_relocate_section (bfd *output_bfd,
|
|||||||
break;
|
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);
|
||||||
|
dogot:
|
||||||
case (int) R_MICROBLAZE_GOT_64:
|
case (int) R_MICROBLAZE_GOT_64:
|
||||||
{
|
{
|
||||||
|
bfd_vma *offp;
|
||||||
|
bfd_vma off, off2;
|
||||||
|
unsigned long indx;
|
||||||
|
bfd_vma static_value;
|
||||||
|
|
||||||
|
bfd_boolean need_relocs = FALSE;
|
||||||
if (htab->sgot == NULL)
|
if (htab->sgot == NULL)
|
||||||
abort ();
|
abort ();
|
||||||
if (h == NULL)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (info->shared)
|
indx = 0;
|
||||||
{
|
offp = NULL;
|
||||||
Elf_Internal_Rela outrel;
|
|
||||||
bfd_byte *loc;
|
/* 1. Identify GOT Offset;
|
||||||
if (htab->srelgot == NULL)
|
2. Compute Static Values
|
||||||
abort ();
|
3. Process Module Id, Process Offset
|
||||||
outrel.r_offset = (htab->sgot->output_section->vma
|
4. Fixup Relocation with GOT offset value. */
|
||||||
+ htab->sgot->output_offset
|
|
||||||
+ off);
|
/* 1. Determine GOT Offset to use : TLS_LD, global, local */
|
||||||
outrel.r_info = ELF32_R_INFO (0, R_MICROBLAZE_REL);
|
if (IS_TLS_LD (tls_type))
|
||||||
outrel.r_addend = relocation + addend;
|
offp = &htab->tlsld_got.offset;
|
||||||
loc = htab->srelgot->contents;
|
else if (h != NULL)
|
||||||
loc += htab->srelgot->reloc_count++
|
{
|
||||||
* sizeof (Elf32_External_Rela);
|
if (htab->sgotplt != NULL && h->got.offset != (bfd_vma) -1)
|
||||||
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
|
offp = &h->got.offset;
|
||||||
}
|
else
|
||||||
local_got_offsets[r_symndx] |= 1;
|
abort ();
|
||||||
}
|
|
||||||
relocation = htab->sgot->output_section->vma
|
|
||||||
+ htab->sgot->output_offset + off
|
|
||||||
- htab->sgotplt->output_section->vma
|
|
||||||
- htab->sgotplt->output_offset;
|
|
||||||
unresolved_reloc = FALSE;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (htab->sgotplt != NULL && h != NULL
|
if (local_got_offsets == NULL)
|
||||||
&& h->got.offset != (bfd_vma) -1)
|
abort ();
|
||||||
|
offp = &local_got_offsets[r_symndx];
|
||||||
|
}
|
||||||
|
|
||||||
|
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, info->shared, h)
|
||||||
|
&& (!info->shared || !SYMBOL_REFERENCES_LOCAL (info, h)))
|
||||||
|
indx = h->dynindx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Need to generate relocs ? */
|
||||||
|
if ((info->shared || 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) )
|
||||||
|
{
|
||||||
|
bfd_vma got_offset;
|
||||||
|
|
||||||
|
got_offset = (htab->sgot->output_section->vma
|
||||||
|
+ htab->sgot->output_offset
|
||||||
|
+ off);
|
||||||
|
|
||||||
|
/* Process module-id */
|
||||||
|
if (IS_TLS_LD(tls_type))
|
||||||
{
|
{
|
||||||
bfd_put_32 (output_bfd, relocation + addend,
|
if (! info->shared)
|
||||||
htab->sgot->contents + h->got.offset);
|
{
|
||||||
relocation = htab->sgot->output_section->vma
|
bfd_put_32 (output_bfd, 1, htab->sgot->contents + off);
|
||||||
+ htab->sgot->output_offset
|
}
|
||||||
+ h->got.offset
|
else
|
||||||
- htab->sgotplt->output_section->vma
|
{
|
||||||
- htab->sgotplt->output_offset;
|
microblaze_elf_output_dynamic_relocation (output_bfd,
|
||||||
unresolved_reloc = FALSE;
|
htab->srelgot, htab->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->sgot->contents + off);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
microblaze_elf_output_dynamic_relocation (output_bfd,
|
||||||
|
htab->srelgot,
|
||||||
|
htab->srelgot->reloc_count++,
|
||||||
|
/* symindex= */ indx, R_MICROBLAZE_TLSDTPMOD32,
|
||||||
|
got_offset, indx ? 0 : static_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process Offset */
|
||||||
|
if (htab->srelgot == NULL)
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
got_offset = (htab->sgot->output_section->vma
|
||||||
|
+ htab->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->sgot->contents + off2);
|
||||||
|
}
|
||||||
|
else if (IS_TLS_GD(tls_type))
|
||||||
|
{
|
||||||
|
*offp |= 1;
|
||||||
|
static_value -= dtprel_base(info);
|
||||||
|
if (need_relocs)
|
||||||
|
{
|
||||||
|
microblaze_elf_output_dynamic_relocation (output_bfd,
|
||||||
|
htab->srelgot, htab->srelgot->reloc_count++,
|
||||||
|
/* symindex= */ indx, R_MICROBLAZE_TLSDTPREL32,
|
||||||
|
got_offset, indx ? 0 : static_value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bfd_put_32 (output_bfd, static_value,
|
||||||
|
htab->sgot->contents + off2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
abort (); /* ??? */
|
{
|
||||||
|
bfd_put_32 (output_bfd, static_value,
|
||||||
|
htab->sgot->contents + off2);
|
||||||
|
|
||||||
|
/* Relocs for dyn symbols generated by
|
||||||
|
finish_dynamic_symbols */
|
||||||
|
if (info->shared && h == NULL)
|
||||||
|
{
|
||||||
|
*offp |= 1;
|
||||||
|
microblaze_elf_output_dynamic_relocation (output_bfd,
|
||||||
|
htab->srelgot, htab->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->sgot->output_section->vma
|
||||||
|
+ htab->sgot->output_offset
|
||||||
|
+ off
|
||||||
|
- htab->sgotplt->output_section->vma
|
||||||
|
- htab->sgotplt->output_offset;
|
||||||
|
|
||||||
|
/* Apply Current Relocation */
|
||||||
bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
|
bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
|
||||||
contents + offset + endian);
|
contents + offset + endian);
|
||||||
bfd_put_16 (input_bfd, relocation & 0xffff,
|
bfd_put_16 (input_bfd, relocation & 0xffff,
|
||||||
contents + offset + endian + INST_WORD_SIZE);
|
contents + offset + endian + INST_WORD_SIZE);
|
||||||
|
|
||||||
|
unresolved_reloc = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1064,6 +1383,14 @@ microblaze_elf_relocate_section (bfd *output_bfd,
|
|||||||
break;
|
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_PCREL :
|
||||||
case (int) R_MICROBLAZE_64:
|
case (int) R_MICROBLAZE_64:
|
||||||
case (int) R_MICROBLAZE_32:
|
case (int) R_MICROBLAZE_32:
|
||||||
@ -1941,6 +2268,33 @@ create_got_section (bfd *dynobj, struct bfd_link_info *info)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bfd_boolean
|
||||||
|
update_local_sym_info (bfd *abfd,
|
||||||
|
Elf_Internal_Shdr *symtab_hdr,
|
||||||
|
unsigned long r_symndx,
|
||||||
|
unsigned int tls_type)
|
||||||
|
{
|
||||||
|
bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (abfd);
|
||||||
|
unsigned char *local_got_tls_masks;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
/* Look through the relocs for a section during the first phase. */
|
/* Look through the relocs for a section during the first phase. */
|
||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
@ -1977,6 +2331,7 @@ microblaze_elf_check_relocs (bfd * abfd,
|
|||||||
unsigned int r_type;
|
unsigned int r_type;
|
||||||
struct elf_link_hash_entry * h;
|
struct elf_link_hash_entry * h;
|
||||||
unsigned long r_symndx;
|
unsigned long r_symndx;
|
||||||
|
unsigned char tls_type = 0;
|
||||||
|
|
||||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||||
r_type = ELF32_R_TYPE (rel->r_info);
|
r_type = ELF32_R_TYPE (rel->r_info);
|
||||||
@ -2012,6 +2367,13 @@ microblaze_elf_check_relocs (bfd * abfd,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
/* This relocation requires .got entry. */
|
/* 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);
|
||||||
|
dogottls:
|
||||||
|
sec->has_tls_reloc = 1;
|
||||||
case R_MICROBLAZE_GOT_64:
|
case R_MICROBLAZE_GOT_64:
|
||||||
if (htab->sgot == NULL)
|
if (htab->sgot == NULL)
|
||||||
{
|
{
|
||||||
@ -2023,25 +2385,12 @@ microblaze_elf_check_relocs (bfd * abfd,
|
|||||||
if (h != NULL)
|
if (h != NULL)
|
||||||
{
|
{
|
||||||
h->got.refcount += 1;
|
h->got.refcount += 1;
|
||||||
|
elf32_mb_hash_entry (h)->tls_mask |= tls_type;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bfd_signed_vma *local_got_refcounts;
|
if (! update_local_sym_info(abfd, symtab_hdr, r_symndx, tls_type) )
|
||||||
|
return FALSE;
|
||||||
/* 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;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2105,45 +2454,16 @@ microblaze_elf_check_relocs (bfd * abfd,
|
|||||||
|
|
||||||
if (sreloc == NULL)
|
if (sreloc == NULL)
|
||||||
{
|
{
|
||||||
const char *name;
|
|
||||||
bfd *dynobj;
|
bfd *dynobj;
|
||||||
unsigned int strndx = elf_elfheader (abfd)->e_shstrndx;
|
|
||||||
unsigned int shnam = _bfd_elf_single_rel_hdr (sec)->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)
|
if (htab->elf.dynobj == NULL)
|
||||||
htab->elf.dynobj = abfd;
|
htab->elf.dynobj = abfd;
|
||||||
dynobj = htab->elf.dynobj;
|
dynobj = htab->elf.dynobj;
|
||||||
|
|
||||||
sreloc = bfd_get_linker_section (dynobj, name);
|
sreloc = _bfd_elf_make_dynamic_reloc_section (sec, dynobj,
|
||||||
|
2, abfd, 1);
|
||||||
if (sreloc == NULL)
|
if (sreloc == NULL)
|
||||||
{
|
return FALSE;
|
||||||
flagword flags;
|
|
||||||
|
|
||||||
flags = (SEC_HAS_CONTENTS | SEC_READONLY
|
|
||||||
| SEC_IN_MEMORY | SEC_LINKER_CREATED);
|
|
||||||
if ((sec->flags & SEC_ALLOC) != 0)
|
|
||||||
flags |= SEC_ALLOC | SEC_LOAD;
|
|
||||||
sreloc = bfd_make_section_anyway_with_flags (dynobj,
|
|
||||||
name,
|
|
||||||
flags);
|
|
||||||
if (sreloc == NULL
|
|
||||||
|| ! bfd_set_section_alignment (dynobj, sreloc, 2))
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
elf_section_data (sec)->sreloc = sreloc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this is a global symbol, we count the number of
|
/* If this is a global symbol, we count the number of
|
||||||
@ -2274,6 +2594,8 @@ microblaze_elf_copy_indirect_symbol (struct bfd_link_info *info,
|
|||||||
eind->dyn_relocs = NULL;
|
eind->dyn_relocs = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
edir->tls_mask |= eind->tls_mask;
|
||||||
|
|
||||||
_bfd_elf_link_hash_copy_indirect (info, dir, ind);
|
_bfd_elf_link_hash_copy_indirect (info, dir, ind);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2492,8 +2814,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * dat)
|
|||||||
h->needs_plt = 0;
|
h->needs_plt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eh = (struct elf32_mb_link_hash_entry *) h;
|
||||||
if (h->got.refcount > 0)
|
if (h->got.refcount > 0)
|
||||||
{
|
{
|
||||||
|
unsigned int need;
|
||||||
asection *s;
|
asection *s;
|
||||||
|
|
||||||
/* Make sure this symbol is output as a dynamic symbol.
|
/* Make sure this symbol is output as a dynamic symbol.
|
||||||
@ -2505,15 +2829,43 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * dat)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
s = htab->sgot;
|
need = 0;
|
||||||
h->got.offset = s->size;
|
if ((eh->tls_mask & TLS_TLS) != 0)
|
||||||
s->size += 4;
|
{
|
||||||
htab->srelgot->size += sizeof (Elf32_External_Rela);
|
/* 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->sgot;
|
||||||
|
h->got.offset = s->size;
|
||||||
|
s->size += need;
|
||||||
|
htab->srelgot->size += need * (sizeof (Elf32_External_Rela) / 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
h->got.offset = (bfd_vma) -1;
|
h->got.offset = (bfd_vma) -1;
|
||||||
|
|
||||||
eh = (struct elf32_mb_link_hash_entry *) h;
|
|
||||||
if (eh->dyn_relocs == NULL)
|
if (eh->dyn_relocs == NULL)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
@ -2611,6 +2963,7 @@ microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||||||
bfd_signed_vma *end_local_got;
|
bfd_signed_vma *end_local_got;
|
||||||
bfd_size_type locsymcount;
|
bfd_size_type locsymcount;
|
||||||
Elf_Internal_Shdr *symtab_hdr;
|
Elf_Internal_Shdr *symtab_hdr;
|
||||||
|
unsigned char *lgot_masks;
|
||||||
asection *srel;
|
asection *srel;
|
||||||
|
|
||||||
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
|
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
|
||||||
@ -2650,17 +3003,36 @@ microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||||||
symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
|
symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
|
||||||
locsymcount = symtab_hdr->sh_info;
|
locsymcount = symtab_hdr->sh_info;
|
||||||
end_local_got = local_got + locsymcount;
|
end_local_got = local_got + locsymcount;
|
||||||
|
lgot_masks = (unsigned char *) end_local_got;
|
||||||
s = htab->sgot;
|
s = htab->sgot;
|
||||||
srel = htab->srelgot;
|
srel = htab->srelgot;
|
||||||
|
|
||||||
for (; local_got < end_local_got; ++local_got)
|
for (; local_got < end_local_got; ++local_got, ++lgot_masks)
|
||||||
{
|
{
|
||||||
if (*local_got > 0)
|
if (*local_got > 0)
|
||||||
{
|
{
|
||||||
*local_got = s->size;
|
unsigned int need = 0;
|
||||||
s->size += 4;
|
if ((*lgot_masks & TLS_TLS) != 0)
|
||||||
if (info->shared)
|
{
|
||||||
srel->size += sizeof (Elf32_External_Rela);
|
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 (info->shared)
|
||||||
|
srel->size += need * (sizeof (Elf32_External_Rela) / 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
*local_got = (bfd_vma) -1;
|
*local_got = (bfd_vma) -1;
|
||||||
@ -2671,6 +3043,16 @@ microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||||||
sym dynamic relocs. */
|
sym dynamic relocs. */
|
||||||
elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
|
elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
|
||||||
|
|
||||||
|
if (htab->tlsld_got.refcount > 0)
|
||||||
|
{
|
||||||
|
htab->tlsld_got.offset = htab->sgot->size;
|
||||||
|
htab->sgot->size += 8;
|
||||||
|
if (info->shared)
|
||||||
|
htab->srelgot->size += sizeof (Elf32_External_Rela);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
htab->tlsld_got.offset = (bfd_vma) -1;
|
||||||
|
|
||||||
if (elf_hash_table (info)->dynamic_sections_created)
|
if (elf_hash_table (info)->dynamic_sections_created)
|
||||||
{
|
{
|
||||||
/* Make space for the trailing nop in .plt. */
|
/* Make space for the trailing nop in .plt. */
|
||||||
@ -2789,6 +3171,7 @@ microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
|
|||||||
Elf_Internal_Sym *sym)
|
Elf_Internal_Sym *sym)
|
||||||
{
|
{
|
||||||
struct elf32_mb_link_hash_table *htab;
|
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);
|
htab = elf32_mb_hash_table (info);
|
||||||
if (htab == NULL)
|
if (htab == NULL)
|
||||||
@ -2860,12 +3243,14 @@ microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 *sgot;
|
||||||
asection *srela;
|
asection *srela;
|
||||||
Elf_Internal_Rela rela;
|
bfd_vma offset;
|
||||||
bfd_byte *loc;
|
|
||||||
|
|
||||||
/* This symbol has an entry in the global offset table. Set it
|
/* This symbol has an entry in the global offset table. Set it
|
||||||
up. */
|
up. */
|
||||||
@ -2874,8 +3259,7 @@ microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
|
|||||||
srela = htab->srelgot;
|
srela = htab->srelgot;
|
||||||
BFD_ASSERT (sgot != NULL && srela != NULL);
|
BFD_ASSERT (sgot != NULL && srela != NULL);
|
||||||
|
|
||||||
rela.r_offset = (sgot->output_section->vma
|
offset = (sgot->output_section->vma + sgot->output_offset
|
||||||
+ sgot->output_offset
|
|
||||||
+ (h->got.offset &~ (bfd_vma) 1));
|
+ (h->got.offset &~ (bfd_vma) 1));
|
||||||
|
|
||||||
/* If this is a -Bsymbolic link, and the symbol is defined
|
/* If this is a -Bsymbolic link, and the symbol is defined
|
||||||
@ -2888,22 +3272,25 @@ microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
|
|||||||
&& h->def_regular)
|
&& h->def_regular)
|
||||||
{
|
{
|
||||||
asection *sec = h->root.u.def.section;
|
asection *sec = h->root.u.def.section;
|
||||||
rela.r_info = ELF32_R_INFO (0, R_MICROBLAZE_REL);
|
microblaze_elf_output_dynamic_relocation (output_bfd,
|
||||||
rela.r_addend = (h->root.u.def.value
|
srela, srela->reloc_count++,
|
||||||
+ sec->output_section->vma
|
/* symindex= */ 0,
|
||||||
+ sec->output_offset);
|
R_MICROBLAZE_REL, offset,
|
||||||
|
h->root.u.def.value
|
||||||
|
+ sec->output_section->vma
|
||||||
|
+ sec->output_offset);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_GLOB_DAT);
|
microblaze_elf_output_dynamic_relocation (output_bfd,
|
||||||
rela.r_addend = 0;
|
srela, srela->reloc_count++,
|
||||||
|
h->dynindx,
|
||||||
|
R_MICROBLAZE_GLOB_DAT,
|
||||||
|
offset, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bfd_put_32 (output_bfd, (bfd_vma) 0,
|
bfd_put_32 (output_bfd, (bfd_vma) 0,
|
||||||
sgot->contents + (h->got.offset &~ (bfd_vma) 1));
|
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)
|
if (h->needs_copy)
|
||||||
@ -3073,7 +3460,7 @@ microblaze_elf_add_symbol_hook (bfd *abfd,
|
|||||||
#define ELF_TARGET_ID MICROBLAZE_ELF_DATA
|
#define ELF_TARGET_ID MICROBLAZE_ELF_DATA
|
||||||
#define ELF_MACHINE_CODE EM_MICROBLAZE
|
#define ELF_MACHINE_CODE EM_MICROBLAZE
|
||||||
#define ELF_MACHINE_ALT1 EM_MICROBLAZE_OLD
|
#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 microblaze_elf_info_to_howto
|
||||||
#define elf_info_to_howto_rel NULL
|
#define elf_info_to_howto_rel NULL
|
||||||
|
|
||||||
|
@ -2420,6 +2420,14 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
|
|||||||
"BFD_RELOC_MICROBLAZE_64_GOTOFF",
|
"BFD_RELOC_MICROBLAZE_64_GOTOFF",
|
||||||
"BFD_RELOC_MICROBLAZE_32_GOTOFF",
|
"BFD_RELOC_MICROBLAZE_32_GOTOFF",
|
||||||
"BFD_RELOC_MICROBLAZE_COPY",
|
"BFD_RELOC_MICROBLAZE_COPY",
|
||||||
|
"BFD_RELOC_MICROBLAZE_64_TLS",
|
||||||
|
"BFD_RELOC_MICROBLAZE_64_TLSGD",
|
||||||
|
"BFD_RELOC_MICROBLAZE_64_TLSLD",
|
||||||
|
"BFD_RELOC_MICROBLAZE_32_TLSDTPMOD",
|
||||||
|
"BFD_RELOC_MICROBLAZE_32_TLSDTPREL",
|
||||||
|
"BFD_RELOC_MICROBLAZE_64_TLSDTPREL",
|
||||||
|
"BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL",
|
||||||
|
"BFD_RELOC_MICROBLAZE_64_TLSTPREL",
|
||||||
"BFD_RELOC_AARCH64_ADD_LO12",
|
"BFD_RELOC_AARCH64_ADD_LO12",
|
||||||
"BFD_RELOC_AARCH64_GOT_LD_PREL19",
|
"BFD_RELOC_AARCH64_GOT_LD_PREL19",
|
||||||
"BFD_RELOC_AARCH64_ADR_GOT_PAGE",
|
"BFD_RELOC_AARCH64_ADR_GOT_PAGE",
|
||||||
|
39
bfd/reloc.c
39
bfd/reloc.c
@ -5882,6 +5882,45 @@ ENUM
|
|||||||
ENUMDOC
|
ENUMDOC
|
||||||
This is used to tell the dynamic linker to copy the value out of
|
This is used to tell the dynamic linker to copy the value out of
|
||||||
the dynamic object into the runtime process image.
|
the dynamic object into the runtime process image.
|
||||||
|
ENUM
|
||||||
|
BFD_RELOC_MICROBLAZE_64_TLS
|
||||||
|
ENUMDOC
|
||||||
|
Unused Reloc
|
||||||
|
ENUM
|
||||||
|
BFD_RELOC_MICROBLAZE_64_TLSGD
|
||||||
|
ENUMDOC
|
||||||
|
This is a 64 bit reloc that stores the 32 bit GOT relative value
|
||||||
|
of the GOT TLS GD info entry in two words (with an imm instruction). The
|
||||||
|
relocation is GOT offset.
|
||||||
|
ENUM
|
||||||
|
BFD_RELOC_MICROBLAZE_64_TLSLD
|
||||||
|
ENUMDOC
|
||||||
|
This is a 64 bit reloc that stores the 32 bit GOT relative value
|
||||||
|
of the GOT TLS LD info entry in two words (with an imm instruction). The
|
||||||
|
relocation is GOT offset.
|
||||||
|
ENUM
|
||||||
|
BFD_RELOC_MICROBLAZE_32_TLSDTPMOD
|
||||||
|
ENUMDOC
|
||||||
|
This is a 32 bit reloc that stores the Module ID to GOT(n).
|
||||||
|
ENUM
|
||||||
|
BFD_RELOC_MICROBLAZE_32_TLSDTPREL
|
||||||
|
ENUMDOC
|
||||||
|
This is a 32 bit reloc that stores TLS offset to GOT(n+1).
|
||||||
|
ENUM
|
||||||
|
BFD_RELOC_MICROBLAZE_64_TLSDTPREL
|
||||||
|
ENUMDOC
|
||||||
|
This is a 32 bit reloc for storing TLS offset to two words (uses imm
|
||||||
|
instruction)
|
||||||
|
ENUM
|
||||||
|
BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL
|
||||||
|
ENUMDOC
|
||||||
|
This is a 64 bit reloc that stores 32-bit thread pointer relative offset
|
||||||
|
to two words (uses imm instruction).
|
||||||
|
ENUM
|
||||||
|
BFD_RELOC_MICROBLAZE_64_TLSTPREL
|
||||||
|
ENUMDOC
|
||||||
|
This is a 64 bit reloc that stores 32-bit thread pointer relative offset
|
||||||
|
to two words (uses imm instruction).
|
||||||
|
|
||||||
ENUM
|
ENUM
|
||||||
BFD_RELOC_AARCH64_ADD_LO12
|
BFD_RELOC_AARCH64_ADD_LO12
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
2012-12-11 Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||||
|
|
||||||
|
* config/tc-microblaze.c: Define TLS offsets
|
||||||
|
(md_relax_table): Add TLS offsets
|
||||||
|
(imm_types), (match_imm), (get_imm_otype): New to support TLS offsets.
|
||||||
|
(tc_microblaze_fix_adjustable): Add TLS relocs.
|
||||||
|
(md_convert_frag): Support TLS offsets.
|
||||||
|
(md_apply_fix), (md_estimate_size_before_relax), (tc_gen_reloc):
|
||||||
|
Add TLS relocs
|
||||||
|
|
||||||
2012-12-06 Yufeng Zhang <yufeng.zhang@arm.com>
|
2012-12-06 Yufeng Zhang <yufeng.zhang@arm.com>
|
||||||
|
|
||||||
* config/tc-aarch64.c (exp_has_bignum_p): Remove.
|
* config/tc-aarch64.c (exp_has_bignum_p): Remove.
|
||||||
|
@ -81,7 +81,12 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP";
|
|||||||
#define GOT_OFFSET 8
|
#define GOT_OFFSET 8
|
||||||
#define PLT_OFFSET 9
|
#define PLT_OFFSET 9
|
||||||
#define GOTOFF_OFFSET 10
|
#define GOTOFF_OFFSET 10
|
||||||
|
#define TLSGD_OFFSET 11
|
||||||
|
#define TLSLD_OFFSET 12
|
||||||
|
#define TLSDTPMOD_OFFSET 13
|
||||||
|
#define TLSDTPREL_OFFSET 14
|
||||||
|
#define TLSGOTTPREL_OFFSET 15
|
||||||
|
#define TLSTPREL_OFFSET 16
|
||||||
|
|
||||||
/* Initialize the relax table. */
|
/* Initialize the relax table. */
|
||||||
const relax_typeS md_relax_table[] =
|
const relax_typeS md_relax_table[] =
|
||||||
@ -97,6 +102,12 @@ const relax_typeS md_relax_table[] =
|
|||||||
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 8: GOT_OFFSET. */
|
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 8: GOT_OFFSET. */
|
||||||
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 9: PLT_OFFSET. */
|
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 9: PLT_OFFSET. */
|
||||||
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 10: GOTOFF_OFFSET. */
|
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 10: GOTOFF_OFFSET. */
|
||||||
|
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 11: TLSGD_OFFSET. */
|
||||||
|
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 12: TLSLD_OFFSET. */
|
||||||
|
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*1, 0 }, /* 13: TLSDTPMOD_OFFSET. */
|
||||||
|
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 14: TLSDTPREL_OFFSET. */
|
||||||
|
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 15: TLSGOTTPREL_OFFSET. */
|
||||||
|
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 } /* 16: TLSTPREL_OFFSET. */
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct hash_control * opcode_hash_control; /* Opcode mnemonics. */
|
static struct hash_control * opcode_hash_control; /* Opcode mnemonics. */
|
||||||
@ -599,9 +610,75 @@ parse_exp (char *s, expressionS *e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Symbol modifiers (@GOT, @PLT, @GOTOFF). */
|
/* Symbol modifiers (@GOT, @PLT, @GOTOFF). */
|
||||||
|
#define IMM_NONE 0
|
||||||
#define IMM_GOT 1
|
#define IMM_GOT 1
|
||||||
#define IMM_PLT 2
|
#define IMM_PLT 2
|
||||||
#define IMM_GOTOFF 3
|
#define IMM_GOTOFF 3
|
||||||
|
#define IMM_TLSGD 4
|
||||||
|
#define IMM_TLSLD 5
|
||||||
|
#define IMM_TLSDTPMOD 6
|
||||||
|
#define IMM_TLSDTPREL 7
|
||||||
|
#define IMM_TLSTPREL 8
|
||||||
|
#define IMM_MAX 9
|
||||||
|
|
||||||
|
struct imm_type {
|
||||||
|
char *isuffix; /* Suffix String */
|
||||||
|
int itype; /* Suffix Type */
|
||||||
|
int otype; /* Offset Type */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* These are NOT in assending order of type, GOTOFF is ahead to make
|
||||||
|
sure @GOTOFF does not get matched with @GOT */
|
||||||
|
static struct imm_type imm_types[] = {
|
||||||
|
{ "NONE", IMM_NONE , 0 },
|
||||||
|
{ "GOTOFF", IMM_GOTOFF , GOTOFF_OFFSET },
|
||||||
|
{ "GOT", IMM_GOT , GOT_OFFSET },
|
||||||
|
{ "PLT", IMM_PLT , PLT_OFFSET },
|
||||||
|
{ "TLSGD", IMM_TLSGD , TLSGD_OFFSET },
|
||||||
|
{ "TLSLDM", IMM_TLSLD, TLSLD_OFFSET },
|
||||||
|
{ "TLSDTPMOD", IMM_TLSDTPMOD, TLSDTPMOD_OFFSET },
|
||||||
|
{ "TLSDTPREL", IMM_TLSDTPREL, TLSDTPREL_OFFSET },
|
||||||
|
{ "TLSTPREL", IMM_TLSTPREL, TLSTPREL_OFFSET }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
match_imm (const char *s, int *ilen)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int slen;
|
||||||
|
|
||||||
|
/* Check for matching suffix */
|
||||||
|
for (i = 1; i < IMM_MAX; i++)
|
||||||
|
{
|
||||||
|
slen = strlen (imm_types[i].isuffix);
|
||||||
|
|
||||||
|
if (strncmp (imm_types[i].isuffix, s, slen) == 0)
|
||||||
|
{
|
||||||
|
*ilen = slen;
|
||||||
|
return imm_types[i].itype;
|
||||||
|
}
|
||||||
|
} /* for */
|
||||||
|
*ilen = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_imm_otype (int itype)
|
||||||
|
{
|
||||||
|
int i, otype;
|
||||||
|
|
||||||
|
otype = 0;
|
||||||
|
/* Check for matching itype */
|
||||||
|
for (i = 1; i < IMM_MAX; i++)
|
||||||
|
{
|
||||||
|
if (imm_types[i].itype == itype)
|
||||||
|
{
|
||||||
|
otype = imm_types[i].otype;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return otype;
|
||||||
|
}
|
||||||
|
|
||||||
static symbolS * GOT_symbol;
|
static symbolS * GOT_symbol;
|
||||||
|
|
||||||
@ -612,6 +689,9 @@ parse_imm (char * s, expressionS * e, int min, int max)
|
|||||||
{
|
{
|
||||||
char *new_pointer;
|
char *new_pointer;
|
||||||
char *atp;
|
char *atp;
|
||||||
|
int itype, ilen;
|
||||||
|
|
||||||
|
ilen = 0;
|
||||||
|
|
||||||
/* Find the start of "@GOT" or "@PLT" suffix (if any) */
|
/* Find the start of "@GOT" or "@PLT" suffix (if any) */
|
||||||
for (atp = s; *atp != '@'; atp++)
|
for (atp = s; *atp != '@'; atp++)
|
||||||
@ -620,26 +700,18 @@ parse_imm (char * s, expressionS * e, int min, int max)
|
|||||||
|
|
||||||
if (*atp == '@')
|
if (*atp == '@')
|
||||||
{
|
{
|
||||||
if (strncmp (atp + 1, "GOTOFF", 5) == 0)
|
itype = match_imm (atp + 1, &ilen);
|
||||||
{
|
if (itype != 0)
|
||||||
*atp = 0;
|
{
|
||||||
e->X_md = IMM_GOTOFF;
|
*atp = 0;
|
||||||
}
|
e->X_md = itype;
|
||||||
else if (strncmp (atp + 1, "GOT", 3) == 0)
|
}
|
||||||
{
|
|
||||||
*atp = 0;
|
|
||||||
e->X_md = IMM_GOT;
|
|
||||||
}
|
|
||||||
else if (strncmp (atp + 1, "PLT", 3) == 0)
|
|
||||||
{
|
|
||||||
*atp = 0;
|
|
||||||
e->X_md = IMM_PLT;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
atp = NULL;
|
atp = NULL;
|
||||||
e->X_md = 0;
|
e->X_md = 0;
|
||||||
}
|
ilen = 0;
|
||||||
|
}
|
||||||
*atp = 0;
|
*atp = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -655,6 +727,11 @@ parse_imm (char * s, expressionS * e, int min, int max)
|
|||||||
|
|
||||||
new_pointer = parse_exp (s, e);
|
new_pointer = parse_exp (s, e);
|
||||||
|
|
||||||
|
if (!GOT_symbol && ! strncmp (s, GOT_SYMBOL_NAME, 20))
|
||||||
|
{
|
||||||
|
GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
if (e->X_op == O_absent)
|
if (e->X_op == O_absent)
|
||||||
; /* An error message has already been emitted. */
|
; /* An error message has already been emitted. */
|
||||||
else if ((e->X_op != O_constant && e->X_op != O_symbol) )
|
else if ((e->X_op != O_constant && e->X_op != O_symbol) )
|
||||||
@ -670,9 +747,7 @@ parse_imm (char * s, expressionS * e, int min, int max)
|
|||||||
{
|
{
|
||||||
*atp = '@'; /* restore back (needed?) */
|
*atp = '@'; /* restore back (needed?) */
|
||||||
if (new_pointer >= atp)
|
if (new_pointer >= atp)
|
||||||
new_pointer += (e->X_md == IMM_GOTOFF)?7:4;
|
new_pointer += ilen + 1; /* sizeof (imm_suffix) + 1 for '@' */
|
||||||
/* sizeof("@GOTOFF", "@GOT" or "@PLT") */
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return new_pointer;
|
return new_pointer;
|
||||||
}
|
}
|
||||||
@ -792,7 +867,14 @@ tc_microblaze_fix_adjustable (struct fix *fixP)
|
|||||||
if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GOTOFF
|
if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GOTOFF
|
||||||
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_GOTOFF
|
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_GOTOFF
|
||||||
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GOT
|
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GOT
|
||||||
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_PLT)
|
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_PLT
|
||||||
|
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSGD
|
||||||
|
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSLD
|
||||||
|
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_TLSDTPMOD
|
||||||
|
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_TLSDTPREL
|
||||||
|
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSDTPREL
|
||||||
|
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL
|
||||||
|
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSTPREL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -940,12 +1022,8 @@ md_assemble (char * str)
|
|||||||
opc = str_microblaze_rw_anchor;
|
opc = str_microblaze_rw_anchor;
|
||||||
else
|
else
|
||||||
opc = NULL;
|
opc = NULL;
|
||||||
if (exp.X_md == IMM_GOT)
|
if (exp.X_md != 0)
|
||||||
subtype = GOT_OFFSET;
|
subtype = get_imm_otype(exp.X_md);
|
||||||
else if (exp.X_md == IMM_PLT)
|
|
||||||
subtype = PLT_OFFSET;
|
|
||||||
else if (exp.X_md == IMM_GOTOFF)
|
|
||||||
subtype = GOTOFF_OFFSET;
|
|
||||||
else
|
else
|
||||||
subtype = opcode->inst_offset_type;
|
subtype = opcode->inst_offset_type;
|
||||||
|
|
||||||
@ -1436,12 +1514,11 @@ md_assemble (char * str)
|
|||||||
char *opc = NULL;
|
char *opc = NULL;
|
||||||
relax_substateT subtype;
|
relax_substateT subtype;
|
||||||
|
|
||||||
if (exp.X_md == IMM_GOT)
|
if (exp.X_md != 0)
|
||||||
subtype = GOT_OFFSET;
|
subtype = get_imm_otype(exp.X_md);
|
||||||
else if (exp.X_md == IMM_PLT)
|
|
||||||
subtype = PLT_OFFSET;
|
|
||||||
else
|
else
|
||||||
subtype = opcode->inst_offset_type;
|
subtype = opcode->inst_offset_type;
|
||||||
|
|
||||||
output = frag_var (rs_machine_dependent,
|
output = frag_var (rs_machine_dependent,
|
||||||
isize * 2, /* maxm of 2 words. */
|
isize * 2, /* maxm of 2 words. */
|
||||||
isize, /* minm of 1 word. */
|
isize, /* minm of 1 word. */
|
||||||
@ -1503,12 +1580,11 @@ md_assemble (char * str)
|
|||||||
char *opc = NULL;
|
char *opc = NULL;
|
||||||
relax_substateT subtype;
|
relax_substateT subtype;
|
||||||
|
|
||||||
if (exp.X_md == IMM_GOT)
|
if (exp.X_md != 0)
|
||||||
subtype = GOT_OFFSET;
|
subtype = get_imm_otype(exp.X_md);
|
||||||
else if (exp.X_md == IMM_PLT)
|
else
|
||||||
subtype = PLT_OFFSET;
|
|
||||||
else
|
|
||||||
subtype = opcode->inst_offset_type;
|
subtype = opcode->inst_offset_type;
|
||||||
|
|
||||||
output = frag_var (rs_machine_dependent,
|
output = frag_var (rs_machine_dependent,
|
||||||
isize * 2, /* maxm of 2 words. */
|
isize * 2, /* maxm of 2 words. */
|
||||||
isize, /* minm of 1 word. */
|
isize, /* minm of 1 word. */
|
||||||
@ -1576,12 +1652,11 @@ md_assemble (char * str)
|
|||||||
char *opc = NULL;
|
char *opc = NULL;
|
||||||
relax_substateT subtype;
|
relax_substateT subtype;
|
||||||
|
|
||||||
if (exp.X_md == IMM_GOT)
|
if (exp.X_md != 0)
|
||||||
subtype = GOT_OFFSET;
|
subtype = get_imm_otype(exp.X_md);
|
||||||
else if (exp.X_md == IMM_PLT)
|
else
|
||||||
subtype = PLT_OFFSET;
|
subtype = opcode->inst_offset_type;
|
||||||
else
|
|
||||||
subtype = opcode->inst_offset_type;
|
|
||||||
output = frag_var (rs_machine_dependent,
|
output = frag_var (rs_machine_dependent,
|
||||||
isize * 2, /* maxm of 2 words. */
|
isize * 2, /* maxm of 2 words. */
|
||||||
isize, /* minm of 1 word. */
|
isize, /* minm of 1 word. */
|
||||||
@ -1847,6 +1922,24 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
|
|||||||
fragP->fr_fix += INST_WORD_SIZE * 2;
|
fragP->fr_fix += INST_WORD_SIZE * 2;
|
||||||
fragP->fr_var = 0;
|
fragP->fr_var = 0;
|
||||||
break;
|
break;
|
||||||
|
case TLSGD_OFFSET:
|
||||||
|
fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
|
||||||
|
fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TLSGD);
|
||||||
|
fragP->fr_fix += INST_WORD_SIZE * 2;
|
||||||
|
fragP->fr_var = 0;
|
||||||
|
break;
|
||||||
|
case TLSLD_OFFSET:
|
||||||
|
fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
|
||||||
|
fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TLSLD);
|
||||||
|
fragP->fr_fix += INST_WORD_SIZE * 2;
|
||||||
|
fragP->fr_var = 0;
|
||||||
|
break;
|
||||||
|
case TLSDTPREL_OFFSET:
|
||||||
|
fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
|
||||||
|
fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TLSDTPREL);
|
||||||
|
fragP->fr_fix += INST_WORD_SIZE * 2;
|
||||||
|
fragP->fr_var = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
abort ();
|
abort ();
|
||||||
@ -2028,6 +2121,11 @@ md_apply_fix (fixS * fixP,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
|
||||||
|
case BFD_RELOC_MICROBLAZE_64_TLSGD:
|
||||||
|
case BFD_RELOC_MICROBLAZE_64_TLSLD:
|
||||||
|
S_SET_THREAD_LOCAL (fixP->fx_addsy);
|
||||||
|
|
||||||
case BFD_RELOC_MICROBLAZE_64_GOTPC:
|
case BFD_RELOC_MICROBLAZE_64_GOTPC:
|
||||||
case BFD_RELOC_MICROBLAZE_64_GOT:
|
case BFD_RELOC_MICROBLAZE_64_GOT:
|
||||||
case BFD_RELOC_MICROBLAZE_64_PLT:
|
case BFD_RELOC_MICROBLAZE_64_PLT:
|
||||||
@ -2206,11 +2304,16 @@ md_estimate_size_before_relax (fragS * fragP,
|
|||||||
case GOT_OFFSET:
|
case GOT_OFFSET:
|
||||||
case PLT_OFFSET:
|
case PLT_OFFSET:
|
||||||
case GOTOFF_OFFSET:
|
case GOTOFF_OFFSET:
|
||||||
|
case TLSGD_OFFSET:
|
||||||
|
case TLSLD_OFFSET:
|
||||||
|
case TLSTPREL_OFFSET:
|
||||||
|
case TLSDTPREL_OFFSET:
|
||||||
fragP->fr_var = INST_WORD_SIZE*2;
|
fragP->fr_var = INST_WORD_SIZE*2;
|
||||||
break;
|
break;
|
||||||
case DEFINED_RO_SEGMENT:
|
case DEFINED_RO_SEGMENT:
|
||||||
case DEFINED_RW_SEGMENT:
|
case DEFINED_RW_SEGMENT:
|
||||||
case DEFINED_PC_OFFSET:
|
case DEFINED_PC_OFFSET:
|
||||||
|
case TLSDTPMOD_OFFSET:
|
||||||
fragP->fr_var = INST_WORD_SIZE;
|
fragP->fr_var = INST_WORD_SIZE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -2294,6 +2397,13 @@ tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
|
|||||||
case BFD_RELOC_MICROBLAZE_64_PLT:
|
case BFD_RELOC_MICROBLAZE_64_PLT:
|
||||||
case BFD_RELOC_MICROBLAZE_64_GOTOFF:
|
case BFD_RELOC_MICROBLAZE_64_GOTOFF:
|
||||||
case BFD_RELOC_MICROBLAZE_32_GOTOFF:
|
case BFD_RELOC_MICROBLAZE_32_GOTOFF:
|
||||||
|
case BFD_RELOC_MICROBLAZE_64_TLSGD:
|
||||||
|
case BFD_RELOC_MICROBLAZE_64_TLSLD:
|
||||||
|
case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD:
|
||||||
|
case BFD_RELOC_MICROBLAZE_32_TLSDTPREL:
|
||||||
|
case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
|
||||||
|
case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL:
|
||||||
|
case BFD_RELOC_MICROBLAZE_64_TLSTPREL:
|
||||||
code = fixp->fx_r_type;
|
code = fixp->fx_r_type;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2012-12-11 Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||||
|
|
||||||
|
* elf/microblaze.h: Add TLS relocs to START_RELOC_NUMBERS
|
||||||
|
|
||||||
2012-11-09 Jason Merrill <jason@redhat.com>
|
2012-11-09 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
* demangle.h (enum demangle_component_type): Add
|
* demangle.h (enum demangle_component_type): Add
|
||||||
|
@ -50,6 +50,14 @@ START_RELOC_NUMBERS (elf_microblaze_reloc_type)
|
|||||||
RELOC_NUMBER (R_MICROBLAZE_GOTOFF_64, 19) /* Offset relative to GOT. */
|
RELOC_NUMBER (R_MICROBLAZE_GOTOFF_64, 19) /* Offset relative to GOT. */
|
||||||
RELOC_NUMBER (R_MICROBLAZE_GOTOFF_32, 20) /* Offset relative to GOT. */
|
RELOC_NUMBER (R_MICROBLAZE_GOTOFF_32, 20) /* Offset relative to GOT. */
|
||||||
RELOC_NUMBER (R_MICROBLAZE_COPY, 21) /* Runtime copy. */
|
RELOC_NUMBER (R_MICROBLAZE_COPY, 21) /* Runtime copy. */
|
||||||
|
RELOC_NUMBER (R_MICROBLAZE_TLS, 22) /* TLS Reloc */
|
||||||
|
RELOC_NUMBER (R_MICROBLAZE_TLSGD, 23) /* TLS General Dynamic */
|
||||||
|
RELOC_NUMBER (R_MICROBLAZE_TLSLD, 24) /* TLS Local Dynamic */
|
||||||
|
RELOC_NUMBER (R_MICROBLAZE_TLSDTPMOD32, 25) /* TLS Module ID */
|
||||||
|
RELOC_NUMBER (R_MICROBLAZE_TLSDTPREL32, 26) /* TLS Offset Within TLS Block */
|
||||||
|
RELOC_NUMBER (R_MICROBLAZE_TLSDTPREL64, 27) /* TLS Offset Within TLS Block */
|
||||||
|
RELOC_NUMBER (R_MICROBLAZE_TLSGOTTPREL32, 28) /* TLS Offset From Thread Pointer */
|
||||||
|
RELOC_NUMBER (R_MICROBLAZE_TLSTPREL32, 29) /* TLS Offset From Thread Pointer */
|
||||||
|
|
||||||
END_RELOC_NUMBERS (R_MICROBLAZE_max)
|
END_RELOC_NUMBERS (R_MICROBLAZE_max)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user