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:
Michael Eager 2012-12-11 16:56:53 +00:00
parent 3e3420f6a1
commit 69b06cc85f
9 changed files with 788 additions and 169 deletions

View file

@ -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>
PR binutils/14933

View file

@ -5071,6 +5071,37 @@ value in a word. The relocation is relative offset from */
the dynamic object into the runtime process image. */
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.
Used in conjunction with BFD_RELOC_AARCH64_ADR_HI21_PCREL. */
BFD_RELOC_AARCH64_ADD_LO12,

View file

@ -370,6 +370,132 @@ static reloc_howto_type microblaze_elf_howto_raw[] =
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
@ -461,6 +587,27 @@ microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
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;
@ -550,8 +697,21 @@ struct elf32_mb_link_hash_entry
/* 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. */
@ -571,8 +731,17 @@ struct elf32_mb_link_hash_table
/* 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) \
@ -604,6 +773,7 @@ link_hash_newfunc (struct bfd_hash_entry *entry,
eh = (struct elf32_mb_link_hash_entry *) entry;
eh->dyn_relocs = NULL;
eh->tls_mask = 0;
}
return entry;
@ -654,6 +824,40 @@ microblaze_elf_final_sdp (struct bfd_link_info *info)
+ 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],
@ -707,6 +911,7 @@ microblaze_elf_relocate_section (bfd *output_bfd,
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 ();
@ -738,6 +943,8 @@ microblaze_elf_relocate_section (bfd *output_bfd,
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"),
@ -971,70 +1178,182 @@ microblaze_elf_relocate_section (bfd *output_bfd,
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:
{
bfd_vma *offp;
bfd_vma off, off2;
unsigned long indx;
bfd_vma static_value;
bfd_boolean need_relocs = FALSE;
if (htab->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->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)
if (!offp)
abort ();
outrel.r_offset = (htab->sgot->output_section->vma
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);
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;
/* Process module-id */
if (IS_TLS_LD(tls_type))
{
if (! info->shared)
{
bfd_put_32 (output_bfd, 1, htab->sgot->contents + off);
}
else
{
if (htab->sgotplt != NULL && h != NULL
&& h->got.offset != (bfd_vma) -1)
microblaze_elf_output_dynamic_relocation (output_bfd,
htab->srelgot, htab->srelgot->reloc_count++,
/* symindex= */ 0, R_MICROBLAZE_TLSDTPMOD32,
got_offset, 0);
}
}
else if (IS_TLS_GD(tls_type))
{
bfd_put_32 (output_bfd, relocation + addend,
htab->sgot->contents + h->got.offset);
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
{
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
+ h->got.offset
+ off
- htab->sgotplt->output_section->vma
- htab->sgotplt->output_offset;
unresolved_reloc = FALSE;
}
else
abort (); /* ??? */
}
/* Apply Current Relocation */
bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
contents + offset + endian);
bfd_put_16 (input_bfd, relocation & 0xffff,
contents + offset + endian + INST_WORD_SIZE);
unresolved_reloc = FALSE;
break;
}
@ -1064,6 +1383,14 @@ microblaze_elf_relocate_section (bfd *output_bfd,
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:
@ -1941,6 +2268,33 @@ create_got_section (bfd *dynobj, struct bfd_link_info *info)
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. */
static bfd_boolean
@ -1977,6 +2331,7 @@ microblaze_elf_check_relocs (bfd * abfd,
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);
@ -2012,6 +2367,13 @@ microblaze_elf_check_relocs (bfd * abfd,
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);
dogottls:
sec->has_tls_reloc = 1;
case R_MICROBLAZE_GOT_64:
if (htab->sgot == NULL)
{
@ -2023,25 +2385,12 @@ microblaze_elf_check_relocs (bfd * abfd,
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)
if (! update_local_sym_info(abfd, symtab_hdr, r_symndx, tls_type) )
return FALSE;
elf_local_got_refcounts (abfd) = local_got_refcounts;
}
local_got_refcounts[r_symndx] += 1;
}
break;
@ -2105,46 +2454,17 @@ microblaze_elf_check_relocs (bfd * abfd,
if (sreloc == NULL)
{
const char *name;
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)
htab->elf.dynobj = abfd;
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)
{
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
relocations we need for this symbol. */
@ -2274,6 +2594,8 @@ microblaze_elf_copy_indirect_symbol (struct bfd_link_info *info,
eind->dyn_relocs = NULL;
}
edir->tls_mask |= eind->tls_mask;
_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;
}
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.
@ -2505,15 +2829,43 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * dat)
return FALSE;
}
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->sgot;
h->got.offset = s->size;
s->size += 4;
htab->srelgot->size += sizeof (Elf32_External_Rela);
s->size += need;
htab->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;
@ -2611,6 +2963,7 @@ microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
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)
@ -2650,17 +3003,36 @@ microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
locsymcount = symtab_hdr->sh_info;
end_local_got = local_got + locsymcount;
lgot_masks = (unsigned char *) end_local_got;
s = htab->sgot;
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)
{
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 += 4;
s->size += need;
if (info->shared)
srel->size += sizeof (Elf32_External_Rela);
srel->size += need * (sizeof (Elf32_External_Rela) / 4);
}
}
else
*local_got = (bfd_vma) -1;
@ -2671,6 +3043,16 @@ microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
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->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)
{
/* Make space for the trailing nop in .plt. */
@ -2789,6 +3171,7 @@ microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
Elf_Internal_Sym *sym)
{
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);
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 *srela;
Elf_Internal_Rela rela;
bfd_byte *loc;
bfd_vma offset;
/* This symbol has an entry in the global offset table. Set it
up. */
@ -2874,8 +3259,7 @@ microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
srela = htab->srelgot;
BFD_ASSERT (sgot != NULL && srela != NULL);
rela.r_offset = (sgot->output_section->vma
+ sgot->output_offset
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
@ -2888,22 +3272,25 @@ microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
&& h->def_regular)
{
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
microblaze_elf_output_dynamic_relocation (output_bfd,
srela, srela->reloc_count++,
/* symindex= */ 0,
R_MICROBLAZE_REL, offset,
h->root.u.def.value
+ sec->output_section->vma
+ sec->output_offset);
}
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)
@ -3073,7 +3460,7 @@ microblaze_elf_add_symbol_hook (bfd *abfd,
#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

View file

@ -2420,6 +2420,14 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_MICROBLAZE_64_GOTOFF",
"BFD_RELOC_MICROBLAZE_32_GOTOFF",
"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_GOT_LD_PREL19",
"BFD_RELOC_AARCH64_ADR_GOT_PAGE",

View file

@ -5882,6 +5882,45 @@ ENUM
ENUMDOC
This is used to tell the dynamic linker to copy the value out of
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
BFD_RELOC_AARCH64_ADD_LO12

View file

@ -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>
* config/tc-aarch64.c (exp_has_bignum_p): Remove.

View file

@ -81,7 +81,12 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP";
#define GOT_OFFSET 8
#define PLT_OFFSET 9
#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. */
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 }, /* 9: PLT_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. */
@ -599,9 +610,75 @@ parse_exp (char *s, expressionS *e)
}
/* Symbol modifiers (@GOT, @PLT, @GOTOFF). */
#define IMM_NONE 0
#define IMM_GOT 1
#define IMM_PLT 2
#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;
@ -612,6 +689,9 @@ parse_imm (char * s, expressionS * e, int min, int max)
{
char *new_pointer;
char *atp;
int itype, ilen;
ilen = 0;
/* Find the start of "@GOT" or "@PLT" suffix (if any) */
for (atp = s; *atp != '@'; atp++)
@ -620,25 +700,17 @@ parse_imm (char * s, expressionS * e, int min, int max)
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;
}
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;
e->X_md = itype;
}
else
{
atp = NULL;
e->X_md = 0;
ilen = 0;
}
*atp = 0;
}
@ -655,6 +727,11 @@ parse_imm (char * s, expressionS * e, int min, int max)
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)
; /* An error message has already been emitted. */
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?) */
if (new_pointer >= atp)
new_pointer += (e->X_md == IMM_GOTOFF)?7:4;
/* sizeof("@GOTOFF", "@GOT" or "@PLT") */
new_pointer += ilen + 1; /* sizeof (imm_suffix) + 1 for '@' */
}
return new_pointer;
}
@ -792,7 +867,14 @@ tc_microblaze_fix_adjustable (struct fix *fixP)
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_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 1;
@ -940,12 +1022,8 @@ md_assemble (char * str)
opc = str_microblaze_rw_anchor;
else
opc = NULL;
if (exp.X_md == IMM_GOT)
subtype = GOT_OFFSET;
else if (exp.X_md == IMM_PLT)
subtype = PLT_OFFSET;
else if (exp.X_md == IMM_GOTOFF)
subtype = GOTOFF_OFFSET;
if (exp.X_md != 0)
subtype = get_imm_otype(exp.X_md);
else
subtype = opcode->inst_offset_type;
@ -1436,12 +1514,11 @@ md_assemble (char * str)
char *opc = NULL;
relax_substateT subtype;
if (exp.X_md == IMM_GOT)
subtype = GOT_OFFSET;
else if (exp.X_md == IMM_PLT)
subtype = PLT_OFFSET;
if (exp.X_md != 0)
subtype = get_imm_otype(exp.X_md);
else
subtype = opcode->inst_offset_type;
output = frag_var (rs_machine_dependent,
isize * 2, /* maxm of 2 words. */
isize, /* minm of 1 word. */
@ -1503,12 +1580,11 @@ md_assemble (char * str)
char *opc = NULL;
relax_substateT subtype;
if (exp.X_md == IMM_GOT)
subtype = GOT_OFFSET;
else if (exp.X_md == IMM_PLT)
subtype = PLT_OFFSET;
if (exp.X_md != 0)
subtype = get_imm_otype(exp.X_md);
else
subtype = opcode->inst_offset_type;
output = frag_var (rs_machine_dependent,
isize * 2, /* maxm of 2 words. */
isize, /* minm of 1 word. */
@ -1576,12 +1652,11 @@ md_assemble (char * str)
char *opc = NULL;
relax_substateT subtype;
if (exp.X_md == IMM_GOT)
subtype = GOT_OFFSET;
else if (exp.X_md == IMM_PLT)
subtype = PLT_OFFSET;
if (exp.X_md != 0)
subtype = get_imm_otype(exp.X_md);
else
subtype = opcode->inst_offset_type;
output = frag_var (rs_machine_dependent,
isize * 2, /* maxm of 2 words. */
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_var = 0;
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:
abort ();
@ -2028,6 +2121,11 @@ md_apply_fix (fixS * fixP,
}
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_GOT:
case BFD_RELOC_MICROBLAZE_64_PLT:
@ -2206,11 +2304,16 @@ md_estimate_size_before_relax (fragS * fragP,
case GOT_OFFSET:
case PLT_OFFSET:
case GOTOFF_OFFSET:
case TLSGD_OFFSET:
case TLSLD_OFFSET:
case TLSTPREL_OFFSET:
case TLSDTPREL_OFFSET:
fragP->fr_var = INST_WORD_SIZE*2;
break;
case DEFINED_RO_SEGMENT:
case DEFINED_RW_SEGMENT:
case DEFINED_PC_OFFSET:
case TLSDTPMOD_OFFSET:
fragP->fr_var = INST_WORD_SIZE;
break;
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_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;
break;

View file

@ -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>
* demangle.h (enum demangle_component_type): Add

View file

@ -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_32, 20) /* Offset relative to GOT. */
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)