This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
alpha tls support
- From: Richard Henderson <rth at redhat dot com>
- To: binutils at sources dot redhat dot com
- Date: Thu, 30 May 2002 15:03:31 -0700
- Subject: alpha tls support
Appears to work. Need to do the gcc and ld.so support to be sure.
r~
include/elf/
* alpha.h (R_ALPHA_TLSGD, R_ALPHA_TLSLDM, R_ALPHA_DTPMOD64,
R_ALPHA_GOTDTPREL, R_ALPHA_DTPREL64, R_ALPHA_DTPRELHI,
R_ALPHA_DTPRELLO, R_ALPHA_DTPREL16, R_ALPHA_GOTTPREL, R_ALPHA_TPREL64,
R_ALPHA_TPRELHI, R_ALPHA_TPRELLO, R_ALPHA_TPREL16): New.
bfd/
* elf64-alpha.c (ALPHA_ELF_LINK_HASH_LU_TLSGD,
ALPHA_ELF_LINK_HASH_LU_TLSLDM, ALPHA_ELF_LINK_HASH_LU_FUNC): New.
(ALPHA_ELF_GOT_ENTRY_RELOCS_DONE): Remove.
(ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED): Remove.
(struct alpha_elf_got_entry): Add reloc_type, reloc_done, reloc_xlated.
(struct alpha_elf_obj_tdata): Rename total_got_entries and
n_local_got_entries to total_got_size and local_got_size.
(elf64_alpha_howto, elf64_alpha_reloc_map): Update for TLS relocs.
(alpha_got_entry_size): New.
(elf64_alpha_relax_with_lituse): Use it.
(elf64_alpha_relax_without_lituse): Likewise.
(MAX_GOT_SIZE): Rename from MAX_GOT_ENTRIES.
(get_got_entry): New.
(elf64_alpha_check_relocs): Handle TLS relocs. Reorganize.
(elf64_alpha_adjust_dynamic_symbol): Test LU_FUNC as a mask.
(elf64_alpha_merge_ind_symbols): Check gotent->reloc_type.
(elf64_alpha_can_merge_gots, elf64_alpha_merge_gots): Likewise.
(elf64_alpha_calc_got_offsets_for_symbol): Use alpha_got_entry_size.
(elf64_alpha_calc_got_offsets): Likewise.
(alpha_dynamic_entries_for_reloc): New.
(elf64_alpha_calc_dynrel_sizes): Use it.
(elf64_alpha_size_dynamic_sections): Likewise.
(elf64_alpha_relocate_section): Handle TLS relocations.
* reloc.c: Add Alpha TLS relocations.
* bfd-in2.h, libbfd.h: Rebuild.
gas/
* expr.h (operatorT): Add O_md17..O_md32.
* config/tc-alpha.c (O_lituse_tlsgd, O_lituse_tlsldm, O_tlsgd,
O_tlsldm, O_gotdtprel, O_dtprelhi, O_dtprello, O_dtprel, O_gottprel,
O_tprelhi, O_tprello, O_tprel): New.
(USER_RELOC_P, alpha_reloc_op_tag, debug_exp): Include them.
(DUMMY_RELOC_LITUSE_TLSGD, DUMMY_RELOC_LITUSE_TLSLDM): New.
(LITUSE_TLSGD, LITUSE_TLSLDM): New.
(struct alpha_reloc_tag): Add master, saw_tlsgd, saw_tlsld,
saw_lu_tlsgd, saw_lu_tlsldm. Make multi_section_p a bit field.
(md_apply_fix3): Handle TLS relocations.
(alpha_force_relocation, alpha_fix_adjustable): Likewise.
(alpha_adjust_symtab_relocs): Sort LITERAL relocs after the
associated TLS reloc. Check lituse_tls relocs match up.
(emit_insn): Handle TLS relocations.
(ldX_op): Remove.
gas/testsuite/
* gas/alpha/elf-tls-1.s, gas/alpha/elf-tls-1.d: New.
* gas/alpha/elf-tls-2.s, gas/alpha/elf-tls-1.l: New.
* gas/alpha/elf-tls-3.s, gas/alpha/elf-tls-1.l: New.
* gas/alpha/alpha.exp: Run them.
Index: bfd/elf64-alpha.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-alpha.c,v
retrieving revision 1.62
diff -c -p -d -r1.62 elf64-alpha.c
*** bfd/elf64-alpha.c 2 May 2002 17:46:59 -0000 1.62
--- bfd/elf64-alpha.c 30 May 2002 21:41:27 -0000
*************** static boolean elf64_alpha_size_got_sect
*** 109,119 ****
--- 109,124 ----
PARAMS ((bfd *, struct bfd_link_info *));
static boolean elf64_alpha_always_size_sections
PARAMS ((bfd *, struct bfd_link_info *));
+ static int alpha_dynamic_entries_for_reloc
+ PARAMS ((int, int, int));
static boolean elf64_alpha_calc_dynrel_sizes
PARAMS ((struct alpha_elf_link_hash_entry *, struct bfd_link_info *));
static boolean elf64_alpha_add_symbol_hook
PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
const char **, flagword *, asection **, bfd_vma *));
+ static struct alpha_elf_got_entry *get_got_entry
+ PARAMS ((bfd *, struct alpha_elf_link_hash_entry *, unsigned long,
+ unsigned long, bfd_vma));
static boolean elf64_alpha_check_relocs
PARAMS((bfd *, struct bfd_link_info *, asection *sec,
const Elf_Internal_Rela *));
*************** struct alpha_elf_link_hash_entry
*** 149,158 ****
int flags;
/* Contexts (LITUSE) in which a literal was referenced. */
! #define ALPHA_ELF_LINK_HASH_LU_ADDR 0x01
! #define ALPHA_ELF_LINK_HASH_LU_MEM 0x02
! #define ALPHA_ELF_LINK_HASH_LU_BYTE 0x04
! #define ALPHA_ELF_LINK_HASH_LU_FUNC 0x08
/* Used to implement multiple .got subsections. */
struct alpha_elf_got_entry
--- 154,166 ----
int flags;
/* Contexts (LITUSE) in which a literal was referenced. */
! #define ALPHA_ELF_LINK_HASH_LU_ADDR 0x01
! #define ALPHA_ELF_LINK_HASH_LU_MEM 0x02
! #define ALPHA_ELF_LINK_HASH_LU_BYTE 0x04
! #define ALPHA_ELF_LINK_HASH_LU_JSR 0x08
! #define ALPHA_ELF_LINK_HASH_LU_TLSGD 0x10
! #define ALPHA_ELF_LINK_HASH_LU_TLSLDM 0x20
! #define ALPHA_ELF_LINK_HASH_LU_FUNC 0x38
/* Used to implement multiple .got subsections. */
struct alpha_elf_got_entry
*************** struct alpha_elf_link_hash_entry
*** 168,180 ****
/* the .got offset for this entry. */
int got_offset;
! int flags;
! /* Additional flags. */
! #define ALPHA_ELF_GOT_ENTRY_RELOCS_DONE 0x10
! #define ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED 0x20
! int use_count;
} *got_entries;
/* used to count non-got, non-plt relocations for delayed sizing
--- 176,195 ----
/* the .got offset for this entry. */
int got_offset;
! /* How many references to this entry? */
! int use_count;
! /* The relocation type of this entry. */
! unsigned char reloc_type;
! /* How a LITERAL is used. */
! unsigned char flags;
!
! /* Have we initialized the dynamic relocation for this entry? */
! unsigned char reloc_done;
!
! /* Have we adjusted this entry for SEC_MERGE? */
! unsigned char reloc_xlated;
} *got_entries;
/* used to count non-got, non-plt relocations for delayed sizing
*************** struct alpha_elf_obj_tdata
*** 361,372 ****
/* For every got, this is the section. */
asection *got;
! /* For every got, this is it's total number of *entries*. */
! int total_got_entries;
! /* For every got, this is the sum of the number of *entries* required
to hold all of the member object's local got. */
! int n_local_got_entries;
};
#define alpha_elf_tdata(abfd) \
--- 376,387 ----
/* For every got, this is the section. */
asection *got;
! /* For every got, this is it's total number of words. */
! int total_got_size;
! /* For every got, this is the sum of the number of words required
to hold all of the member object's local got. */
! int local_got_size;
};
#define alpha_elf_tdata(abfd) \
*************** static reloc_howto_type elf64_alpha_howt
*** 748,753 ****
--- 763,965 ----
0x1fffff, /* src_mask */
0x1fffff, /* dst_mask */
true), /* pcrel_offset */
+
+ /* Creates a tls_index for the symbol in the got. */
+ HOWTO (R_ALPHA_TLSGD, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "TLSGD", /* name */
+ false, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Creates a tls_index for the (current) module in the got. */
+ HOWTO (R_ALPHA_TLSLDM, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "TLSLDM", /* name */
+ false, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A dynamic relocation for a DTP module entry. */
+ HOWTO (R_ALPHA_DTPMOD64, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "DTPMOD64", /* name */
+ false, /* partial_inplace */
+ MINUS_ONE, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Creates a 64-bit offset in the got for the displacement
+ from DTP to the target. */
+ HOWTO (R_ALPHA_GOTDTPREL, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "GOTDTPREL", /* name */
+ false, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A dynamic relocation for a displacement from DTP to the target. */
+ HOWTO (R_ALPHA_DTPREL64, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "DTPREL64", /* name */
+ false, /* partial_inplace */
+ MINUS_ONE, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* The high 16 bits of the displacement from DTP to the target. */
+ HOWTO (R_ALPHA_DTPRELHI, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "DTPRELHI", /* name */
+ false, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* The low 16 bits of the displacement from DTP to the target. */
+ HOWTO (R_ALPHA_DTPRELLO, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "DTPRELLO", /* name */
+ false, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 16-bit displacement from DTP to the target. */
+ HOWTO (R_ALPHA_DTPREL16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "DTPREL16", /* name */
+ false, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Creates a 64-bit offset in the got for the displacement
+ from TP to the target. */
+ HOWTO (R_ALPHA_GOTTPREL, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "GOTTPREL", /* name */
+ false, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A dynamic relocation for a displacement from TP to the target. */
+ HOWTO (R_ALPHA_TPREL64, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "TPREL64", /* name */
+ false, /* partial_inplace */
+ MINUS_ONE, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* The high 16 bits of the displacement from TP to the target. */
+ HOWTO (R_ALPHA_TPRELHI, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "TPRELHI", /* name */
+ false, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* The low 16 bits of the displacement from TP to the target. */
+ HOWTO (R_ALPHA_TPRELLO, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "TPRELLO", /* name */
+ false, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 16-bit displacement from TP to the target. */
+ HOWTO (R_ALPHA_TPREL16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "TPREL16", /* name */
+ false, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
};
/* A relocation function which doesn't do anything. */
*************** static const struct elf_reloc_map elf64_
*** 902,907 ****
--- 1114,1132 ----
{BFD_RELOC_ALPHA_GPREL_LO16, R_ALPHA_GPRELLOW},
{BFD_RELOC_GPREL16, R_ALPHA_GPREL16},
{BFD_RELOC_ALPHA_BRSGP, R_ALPHA_BRSGP},
+ {BFD_RELOC_ALPHA_TLSGD, R_ALPHA_TLSGD},
+ {BFD_RELOC_ALPHA_TLSLDM, R_ALPHA_TLSLDM},
+ {BFD_RELOC_ALPHA_DTPMOD64, R_ALPHA_DTPMOD64},
+ {BFD_RELOC_ALPHA_GOTDTPREL16, R_ALPHA_GOTDTPREL},
+ {BFD_RELOC_ALPHA_DTPREL64, R_ALPHA_DTPREL64},
+ {BFD_RELOC_ALPHA_DTPREL_HI16, R_ALPHA_DTPRELHI},
+ {BFD_RELOC_ALPHA_DTPREL_LO16, R_ALPHA_DTPRELLO},
+ {BFD_RELOC_ALPHA_DTPREL16, R_ALPHA_DTPREL16},
+ {BFD_RELOC_ALPHA_GOTTPREL16, R_ALPHA_GOTTPREL},
+ {BFD_RELOC_ALPHA_TPREL64, R_ALPHA_TPREL64},
+ {BFD_RELOC_ALPHA_TPREL_HI16, R_ALPHA_TPRELHI},
+ {BFD_RELOC_ALPHA_TPREL_LO16, R_ALPHA_TPRELLO},
+ {BFD_RELOC_ALPHA_TPREL16, R_ALPHA_TPREL16},
};
/* Given a BFD reloc type, return a HOWTO structure. */
*************** elf64_alpha_info_to_howto (abfd, cache_p
*** 936,941 ****
--- 1161,1170 ----
BFD_ASSERT (r_type < (unsigned int) R_ALPHA_max);
cache_ptr->howto = &elf64_alpha_howto_table[r_type];
}
+
+ /* These two relocations create a two-word entry in the got. */
+ #define alpha_got_entry_size(r_type) \
+ (r_type == R_ALPHA_TLSGD || r_type == R_ALPHA_TLSLDM ? 16 : 8)
/* These functions do relaxation for Alpha ELF.
*************** elf64_alpha_relax_with_lituse (info, sym
*** 1213,1226 ****
got entry by one, possibly eliminating it. */
if (all_optimized)
{
! info->gotent->use_count -= 1;
! alpha_elf_tdata (info->gotent->gotobj)->total_got_entries -= 1;
! if (!info->h)
! alpha_elf_tdata (info->gotent->gotobj)->n_local_got_entries -= 1;
/* If the literal instruction is no longer needed (it may have been
! reused. We can eliminate it.
! ??? For now, I don't want to deal with compacting the section,
so just nop it out. */
if (!lit_reused)
{
--- 1442,1458 ----
got entry by one, possibly eliminating it. */
if (all_optimized)
{
! if (--info->gotent->use_count == 0)
! {
! int sz = alpha_got_entry_size (info->gotent->reloc_type);
! alpha_elf_tdata (info->gotent->gotobj)->total_got_size -= sz;
! if (!info->h)
! alpha_elf_tdata (info->gotent->gotobj)->local_got_size -= sz;
! }
/* If the literal instruction is no longer needed (it may have been
! reused. We can eliminate it. */
! /* ??? For now, I don't want to deal with compacting the section,
so just nop it out. */
if (!lit_reused)
{
*************** elf64_alpha_relax_without_lituse (info,
*** 1349,1358 ****
/* Reduce the use count on this got entry by one, possibly
eliminating it. */
! info->gotent->use_count -= 1;
! alpha_elf_tdata (info->gotent->gotobj)->total_got_entries -= 1;
! if (!info->h)
! alpha_elf_tdata (info->gotent->gotobj)->n_local_got_entries -= 1;
/* ??? Search forward through this basic block looking for insns
that use the target register. Stop after an insn modifying the
--- 1581,1593 ----
/* Reduce the use count on this got entry by one, possibly
eliminating it. */
! if (--info->gotent->use_count == 0)
! {
! int sz = alpha_got_entry_size (info->gotent->reloc_type);
! alpha_elf_tdata (info->gotent->gotobj)->total_got_size -= sz;
! if (!info->h)
! alpha_elf_tdata (info->gotent->gotobj)->local_got_size -= sz;
! }
/* ??? Search forward through this basic block looking for insns
that use the target register. Stop after an insn modifying the
*************** elf64_alpha_relax_section (abfd, sec, li
*** 1643,1649 ****
#define PLT_ENTRY_WORD2 0
#define PLT_ENTRY_WORD3 0
! #define MAX_GOT_ENTRIES (64*1024 / 8)
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so"
--- 1878,1884 ----
#define PLT_ENTRY_WORD2 0
#define PLT_ENTRY_WORD3 0
! #define MAX_GOT_SIZE (64*1024)
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so"
*************** mips_elf_create_procedure_table (handle,
*** 2256,2261 ****
--- 2491,2576 ----
struct ecoff_debug_info *debug;
*/
+ /* Search for and possibly create a got entry. */
+
+ static struct alpha_elf_got_entry *
+ get_got_entry (abfd, h, r_type, r_symndx, r_addend)
+ bfd *abfd;
+ struct alpha_elf_link_hash_entry *h;
+ unsigned long r_type, r_symndx;
+ bfd_vma r_addend;
+ {
+ struct alpha_elf_got_entry *gotent;
+ struct alpha_elf_got_entry **slot;
+
+ if (h)
+ slot = &h->got_entries;
+ else
+ {
+ /* This is a local .got entry -- record for merge. */
+
+ struct alpha_elf_got_entry **local_got_entries;
+
+ local_got_entries = alpha_elf_tdata(abfd)->local_got_entries;
+ if (!local_got_entries)
+ {
+ bfd_size_type size;
+ Elf_Internal_Shdr *symtab_hdr;
+
+ symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
+ size = symtab_hdr->sh_info;
+ size *= sizeof (struct alpha_elf_got_entry *);
+
+ local_got_entries
+ = (struct alpha_elf_got_entry **) bfd_alloc (abfd, size);
+ if (!local_got_entries)
+ return NULL;
+
+ memset (local_got_entries, 0, (size_t) size);
+ alpha_elf_tdata (abfd)->local_got_entries = local_got_entries;
+ }
+
+ slot = &local_got_entries[r_symndx];
+ }
+
+ for (gotent = *slot; gotent ; gotent = gotent->next)
+ if (gotent->gotobj == abfd
+ && gotent->reloc_type == r_type
+ && gotent->addend == r_addend)
+ break;
+
+ if (!gotent)
+ {
+ int entry_size;
+ bfd_size_type amt;
+
+ amt = sizeof (struct alpha_elf_got_entry);
+ gotent = (struct alpha_elf_got_entry *) bfd_alloc (abfd, amt);
+ if (!gotent)
+ return NULL;
+
+ gotent->gotobj = abfd;
+ gotent->addend = r_addend;
+ gotent->got_offset = -1;
+ gotent->use_count = 1;
+ gotent->reloc_type = r_type;
+ gotent->reloc_done = 0;
+ gotent->reloc_xlated = 0;
+
+ gotent->next = *slot;
+ *slot = gotent;
+
+ entry_size = alpha_got_entry_size (r_type);
+ alpha_elf_tdata (abfd)->total_got_size += entry_size;
+ if (!h)
+ alpha_elf_tdata(abfd)->local_got_size += entry_size;
+ }
+ else
+ gotent->use_count += 1;
+
+ return gotent;
+ }
+
/* Handle dynamic relocations when doing an Alpha ELF link. */
static boolean
*************** elf64_alpha_check_relocs (abfd, info, se
*** 2270,2278 ****
const char *rel_sec_name;
Elf_Internal_Shdr *symtab_hdr;
struct alpha_elf_link_hash_entry **sym_hashes;
- struct alpha_elf_got_entry **local_got_entries;
const Elf_Internal_Rela *rel, *relend;
! int got_created;
bfd_size_type amt;
if (info->relocateable)
--- 2585,2592 ----
const char *rel_sec_name;
Elf_Internal_Shdr *symtab_hdr;
struct alpha_elf_link_hash_entry **sym_hashes;
const Elf_Internal_Rela *rel, *relend;
! boolean got_created;
bfd_size_type amt;
if (info->relocateable)
*************** elf64_alpha_check_relocs (abfd, info, se
*** 2286,2299 ****
rel_sec_name = NULL;
symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
sym_hashes = alpha_elf_sym_hashes(abfd);
! local_got_entries = alpha_elf_tdata(abfd)->local_got_entries;
! got_created = 0;
relend = relocs + sec->reloc_count;
for (rel = relocs; rel < relend; ++rel)
{
unsigned long r_symndx, r_type;
struct alpha_elf_link_hash_entry *h;
r_symndx = ELF64_R_SYM (rel->r_info);
if (r_symndx < symtab_hdr->sh_info)
--- 2600,2622 ----
rel_sec_name = NULL;
symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
sym_hashes = alpha_elf_sym_hashes(abfd);
! got_created = false;
relend = relocs + sec->reloc_count;
for (rel = relocs; rel < relend; ++rel)
{
+ enum {
+ NEED_GOT = 1,
+ NEED_GOT_ENTRY = 2,
+ NEED_DYNREL = 4
+ };
+
unsigned long r_symndx, r_type;
struct alpha_elf_link_hash_entry *h;
+ unsigned int gotent_flags;
+ boolean maybe_dynamic;
+ unsigned int need;
+ bfd_vma addend;
r_symndx = ELF64_R_SYM (rel->r_info);
if (r_symndx < symtab_hdr->sh_info)
*************** elf64_alpha_check_relocs (abfd, info, se
*** 2308,2432 ****
h->root.elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
}
r_type = ELF64_R_TYPE (rel->r_info);
switch (r_type)
{
case R_ALPHA_LITERAL:
! {
! struct alpha_elf_got_entry *gotent;
! int flags = 0;
!
! if (h)
! {
! /* Search for and possibly create a got entry. */
! for (gotent = h->got_entries; gotent ; gotent = gotent->next)
! if (gotent->gotobj == abfd &&
! gotent->addend == rel->r_addend)
! break;
!
! if (!gotent)
! {
! amt = sizeof (struct alpha_elf_got_entry);
! gotent = ((struct alpha_elf_got_entry *)
! bfd_alloc (abfd, amt));
! if (!gotent)
! return false;
!
! gotent->gotobj = abfd;
! gotent->addend = rel->r_addend;
! gotent->got_offset = -1;
! gotent->flags = 0;
! gotent->use_count = 1;
!
! gotent->next = h->got_entries;
! h->got_entries = gotent;
!
! alpha_elf_tdata (abfd)->total_got_entries++;
! }
! else
! gotent->use_count += 1;
! }
! else
! {
! /* This is a local .got entry -- record for merge. */
! if (!local_got_entries)
! {
! bfd_size_type size;
! size = symtab_hdr->sh_info;
! size *= sizeof (struct alpha_elf_got_entry *);
!
! local_got_entries = ((struct alpha_elf_got_entry **)
! bfd_alloc (abfd, size));
! if (!local_got_entries)
! return false;
!
! memset (local_got_entries, 0, (size_t) size);
! alpha_elf_tdata (abfd)->local_got_entries =
! local_got_entries;
! }
!
! for (gotent = local_got_entries[ELF64_R_SYM(rel->r_info)];
! gotent != NULL && gotent->addend != rel->r_addend;
! gotent = gotent->next)
! continue;
! if (!gotent)
! {
! amt = sizeof (struct alpha_elf_got_entry);
! gotent = ((struct alpha_elf_got_entry *)
! bfd_alloc (abfd, amt));
! if (!gotent)
! return false;
!
! gotent->gotobj = abfd;
! gotent->addend = rel->r_addend;
! gotent->got_offset = -1;
! gotent->flags = 0;
! gotent->use_count = 1;
!
! gotent->next = local_got_entries[ELF64_R_SYM(rel->r_info)];
! local_got_entries[ELF64_R_SYM(rel->r_info)] = gotent;
!
! alpha_elf_tdata(abfd)->total_got_entries++;
! alpha_elf_tdata(abfd)->n_local_got_entries++;
! }
! else
! gotent->use_count += 1;
! }
! /* Remember how this literal is used from its LITUSEs.
! This will be important when it comes to decide if we can
! create a .plt entry for a function symbol. */
! if (rel+1 < relend
! && ELF64_R_TYPE (rel[1].r_info) == R_ALPHA_LITUSE)
! {
! do
! {
! ++rel;
! if (rel->r_addend >= 1 && rel->r_addend <= 3)
! flags |= 1 << rel->r_addend;
! }
! while (rel+1 < relend &&
! ELF64_R_TYPE (rel[1].r_info) == R_ALPHA_LITUSE);
! }
! else
! {
! /* No LITUSEs -- presumably the address is not being
! loaded for nothing. */
! flags = ALPHA_ELF_LINK_HASH_LU_ADDR;
! }
! gotent->flags |= flags;
! if (h)
! {
! /* Make a guess as to whether a .plt entry will be needed. */
! if ((h->flags |= flags) == ALPHA_ELF_LINK_HASH_LU_FUNC)
! h->root.elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
! else
! h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
! }
! }
! /* FALLTHRU */
case R_ALPHA_GPDISP:
case R_ALPHA_GPREL16:
--- 2631,2670 ----
h->root.elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
}
+
+ /* We can only get preliminary data on whether a symbol is
+ locally or externally defined, as not all of the input files
+ have yet been processed. Do something with what we know, as
+ this may help reduce memory usage and processing time later. */
+ maybe_dynamic = false;
+ if (h && ((info->shared
+ && (!info->symbolic || info->allow_shlib_undefined))
+ || ! (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
+ || h->root.type == bfd_link_hash_defweak))
+ maybe_dynamic = true;
+
+ need = 0;
+ gotent_flags = 0;
r_type = ELF64_R_TYPE (rel->r_info);
+ addend = rel->r_addend;
switch (r_type)
{
case R_ALPHA_LITERAL:
! need = NEED_GOT | NEED_GOT_ENTRY;
! /* Remember how this literal is used from its LITUSEs.
! This will be important when it comes to decide if we can
! create a .plt entry for a function symbol. */
! while (++rel < relend && ELF64_R_TYPE (rel->r_info) == R_ALPHA_LITUSE)
! if (rel->r_addend >= 1 && rel->r_addend <= 5)
! gotent_flags |= 1 << rel->r_addend;
! --rel;
! /* No LITUSEs -- presumably the address is used somehow. */
! if (gotent_flags == 0)
! gotent_flags = ALPHA_ELF_LINK_HASH_LU_ADDR;
! break;
case R_ALPHA_GPDISP:
case R_ALPHA_GPREL16:
*************** elf64_alpha_check_relocs (abfd, info, se
*** 2434,2442 ****
case R_ALPHA_GPRELHIGH:
case R_ALPHA_GPRELLOW:
case R_ALPHA_BRSGP:
! /* We don't actually use the .got here, but the sections must
! be created before the linker maps input sections to output
! sections. */
if (!got_created)
{
if (!elf64_alpha_create_got_section (abfd, info))
--- 2672,2708 ----
case R_ALPHA_GPRELHIGH:
case R_ALPHA_GPRELLOW:
case R_ALPHA_BRSGP:
! need = NEED_GOT;
! break;
!
! case R_ALPHA_REFLONG:
! case R_ALPHA_REFQUAD:
! if (info->shared || maybe_dynamic)
! need = NEED_DYNREL;
! break;
!
! case R_ALPHA_TLSGD:
! case R_ALPHA_TLSLDM:
! case R_ALPHA_GOTDTPREL:
! need = NEED_GOT | NEED_GOT_ENTRY;
! break;
!
! case R_ALPHA_GOTTPREL:
! need = NEED_GOT | NEED_GOT_ENTRY;
! if (info->shared)
! info->flags |= DF_STATIC_TLS;
! break;
!
! case R_ALPHA_TPREL64:
! if (info->shared || maybe_dynamic)
! need = NEED_DYNREL;
! if (info->shared)
! info->flags |= DF_STATIC_TLS;
! break;
! }
!
! if (need & NEED_GOT)
! {
if (!got_created)
{
if (!elf64_alpha_create_got_section (abfd, info))
*************** elf64_alpha_check_relocs (abfd, info, se
*** 2450,2466 ****
got_created = 1;
}
! break;
! case R_ALPHA_SREL16:
! case R_ALPHA_SREL32:
! case R_ALPHA_SREL64:
! if (h == NULL)
! break;
! /* FALLTHRU */
! case R_ALPHA_REFLONG:
! case R_ALPHA_REFQUAD:
if (rel_sec_name == NULL)
{
rel_sec_name = (bfd_elf_string_from_elf_section
--- 2716,2751 ----
got_created = 1;
}
! }
! if (need & NEED_GOT_ENTRY)
! {
! struct alpha_elf_got_entry *gotent;
! gotent = get_got_entry (abfd, h, r_type, r_symndx, addend);
! if (!gotent)
! return false;
!
! if (gotent_flags)
! {
! gotent->flags |= gotent_flags;
! if (h)
! {
! gotent_flags |= h->flags;
! h->flags = gotent_flags;
!
! /* Make a guess as to whether a .plt entry is needed. */
! if ((gotent_flags & ALPHA_ELF_LINK_HASH_LU_FUNC)
! && !(gotent_flags & ~ALPHA_ELF_LINK_HASH_LU_FUNC))
! h->root.elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
! else
! h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
! }
! }
! }
!
! if (need & NEED_DYNREL)
! {
if (rel_sec_name == NULL)
{
rel_sec_name = (bfd_elf_string_from_elf_section
*************** elf64_alpha_check_relocs (abfd, info, se
*** 2538,2544 ****
if (sec->flags & SEC_READONLY)
info->flags |= DF_TEXTREL;
}
- break;
}
}
--- 2823,2828 ----
*************** elf64_alpha_adjust_dynamic_symbol (info,
*** 2570,2576 ****
&& ((h->type == STT_FUNC
&& !(ah->flags & ALPHA_ELF_LINK_HASH_LU_ADDR))
|| (h->type == STT_NOTYPE
! && ah->flags == ALPHA_ELF_LINK_HASH_LU_FUNC))
/* Don't prevent otherwise valid programs from linking by attempting
to create a new .got entry somewhere. A Correct Solution would be
to add a new .got section to a new object file and let it be merged
--- 2854,2861 ----
&& ((h->type == STT_FUNC
&& !(ah->flags & ALPHA_ELF_LINK_HASH_LU_ADDR))
|| (h->type == STT_NOTYPE
! && (ah->flags & ALPHA_ELF_LINK_HASH_LU_FUNC)
! && !(ah->flags & ~ALPHA_ELF_LINK_HASH_LU_FUNC)))
/* Don't prevent otherwise valid programs from linking by attempting
to create a new .got entry somewhere. A Correct Solution would be
to add a new .got section to a new object file and let it be merged
*************** elf64_alpha_merge_ind_symbols (hi, dummy
*** 2667,2674 ****
{
gin = gi->next;
for (gs = gsh; gs ; gs = gs->next)
! if (gi->gotobj == gs->gotobj && gi->addend == gs->addend)
! goto got_found;
gi->next = hs->got_entries;
hs->got_entries = gi;
got_found:;
--- 2952,2964 ----
{
gin = gi->next;
for (gs = gsh; gs ; gs = gs->next)
! if (gi->gotobj == gs->gotobj
! && gi->reloc_type == gs->reloc_type
! && gi->addend == gs->addend)
! {
! gi->use_count += gs->use_count;
! goto got_found;
! }
gi->next = hs->got_entries;
hs->got_entries = gi;
got_found:;
*************** static boolean
*** 2710,2724 ****
elf64_alpha_can_merge_gots (a, b)
bfd *a, *b;
{
! int total = alpha_elf_tdata (a)->total_got_entries;
bfd *bsub;
/* Trivial quick fallout test. */
! if (total + alpha_elf_tdata (b)->total_got_entries <= MAX_GOT_ENTRIES)
return true;
/* By their nature, local .got entries cannot be merged. */
! if ((total += alpha_elf_tdata (b)->n_local_got_entries) > MAX_GOT_ENTRIES)
return false;
/* Failing the common trivial comparison, we must effectively
--- 3000,3014 ----
elf64_alpha_can_merge_gots (a, b)
bfd *a, *b;
{
! int total = alpha_elf_tdata (a)->total_got_size;
bfd *bsub;
/* Trivial quick fallout test. */
! if (total + alpha_elf_tdata (b)->total_got_size <= MAX_GOT_SIZE)
return true;
/* By their nature, local .got entries cannot be merged. */
! if ((total += alpha_elf_tdata (b)->local_got_size) > MAX_GOT_SIZE)
return false;
/* Failing the common trivial comparison, we must effectively
*************** elf64_alpha_can_merge_gots (a, b)
*** 2749,2758 ****
continue;
for (ae = h->got_entries; ae ; ae = ae->next)
! if (ae->gotobj == a && ae->addend == be->addend)
goto global_found;
! if (++total > MAX_GOT_ENTRIES)
return false;
global_found:;
}
--- 3039,3051 ----
continue;
for (ae = h->got_entries; ae ; ae = ae->next)
! if (ae->gotobj == a
! && ae->reloc_type == be->reloc_type
! && ae->addend == be->addend)
goto global_found;
! total += alpha_got_entry_size (be->reloc_type);
! if (total > MAX_GOT_SIZE)
return false;
global_found:;
}
*************** static void
*** 2768,2781 ****
elf64_alpha_merge_gots (a, b)
bfd *a, *b;
{
! int total = alpha_elf_tdata (a)->total_got_entries;
bfd *bsub;
/* Remember local expansion. */
{
! int e = alpha_elf_tdata (b)->n_local_got_entries;
total += e;
! alpha_elf_tdata (a)->n_local_got_entries += e;
}
for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next)
--- 3061,3074 ----
elf64_alpha_merge_gots (a, b)
bfd *a, *b;
{
! int total = alpha_elf_tdata (a)->total_got_size;
bfd *bsub;
/* Remember local expansion. */
{
! int e = alpha_elf_tdata (b)->local_got_size;
total += e;
! alpha_elf_tdata (a)->local_got_size += e;
}
for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next)
*************** elf64_alpha_merge_gots (a, b)
*** 2825,2831 ****
continue;
for (ae = *start; ae ; ae = ae->next)
! if (ae->gotobj == a && ae->addend == be->addend)
{
ae->flags |= be->flags;
ae->use_count += be->use_count;
--- 3118,3126 ----
continue;
for (ae = *start; ae ; ae = ae->next)
! if (ae->gotobj == a
! && ae->reloc_type == be->reloc_type
! && ae->addend == be->addend)
{
ae->flags |= be->flags;
ae->use_count += be->use_count;
*************** elf64_alpha_merge_gots (a, b)
*** 2833,2839 ****
goto global_found;
}
be->gotobj = a;
! total += 1;
global_found:;
}
--- 3128,3134 ----
goto global_found;
}
be->gotobj = a;
! total += alpha_got_entry_size (be->reloc_type);
global_found:;
}
*************** elf64_alpha_merge_gots (a, b)
*** 2841,2847 ****
alpha_elf_tdata (bsub)->gotobj = a;
}
! alpha_elf_tdata (a)->total_got_entries = total;
/* Merge the two in_got chains. */
{
--- 3136,3142 ----
alpha_elf_tdata (bsub)->gotobj = a;
}
! alpha_elf_tdata (a)->total_got_size = total;
/* Merge the two in_got chains. */
{
*************** elf64_alpha_calc_got_offsets_for_symbol
*** 2874,2880 ****
= &alpha_elf_tdata (gotent->gotobj)->got->_raw_size;
gotent->got_offset = *plge;
! *plge += 8;
}
return true;
--- 3169,3175 ----
= &alpha_elf_tdata (gotent->gotobj)->got->_raw_size;
gotent->got_offset = *plge;
! *plge += alpha_got_entry_size (gotent->reloc_type);
}
return true;
*************** elf64_alpha_calc_got_offsets (info)
*** 2916,2922 ****
if (gotent->use_count > 0)
{
gotent->got_offset = got_offset;
! got_offset += 8;
}
}
--- 3211,3217 ----
if (gotent->use_count > 0)
{
gotent->got_offset = got_offset;
! got_offset += alpha_got_entry_size (gotent->reloc_type);
}
}
*************** elf64_alpha_size_got_sections (output_bf
*** 2950,2962 ****
/* We are assuming no merging has yet ocurred. */
BFD_ASSERT (this_got == i);
! if (alpha_elf_tdata (this_got)->total_got_entries > MAX_GOT_ENTRIES)
{
/* Yikes! A single object file has too many entries. */
(*_bfd_error_handler)
(_("%s: .got subsegment exceeds 64K (size %d)"),
bfd_archive_filename (i),
! alpha_elf_tdata (this_got)->total_got_entries * 8);
return false;
}
--- 3245,3257 ----
/* We are assuming no merging has yet ocurred. */
BFD_ASSERT (this_got == i);
! if (alpha_elf_tdata (this_got)->total_got_size > MAX_GOT_SIZE)
{
/* Yikes! A single object file has too many entries. */
(*_bfd_error_handler)
(_("%s: .got subsegment exceeds 64K (size %d)"),
bfd_archive_filename (i),
! alpha_elf_tdata (this_got)->total_got_size);
return false;
}
*************** elf64_alpha_always_size_sections (output
*** 3037,3042 ****
--- 3332,3371 ----
return true;
}
+ /* The number of dynamic relocations required by a static relocation. */
+
+ static int
+ alpha_dynamic_entries_for_reloc (r_type, dynamic, shared)
+ int r_type, dynamic, shared;
+ {
+ switch (r_type)
+ {
+ /* May appear in GOT entries. */
+ case R_ALPHA_TLSGD:
+ return (dynamic ? 2 : shared ? 1 : 0);
+ case R_ALPHA_TLSLDM:
+ return shared;
+ case R_ALPHA_LITERAL:
+ return dynamic || shared;
+ case R_ALPHA_GOTDTPREL:
+ case R_ALPHA_GOTTPREL:
+ return dynamic;
+
+ /* May appear in data sections. */
+ case R_ALPHA_REFLONG:
+ case R_ALPHA_REFQUAD:
+ return dynamic || shared;
+ case R_ALPHA_SREL64:
+ case R_ALPHA_TPREL64:
+ return dynamic;
+
+ /* Everything else is illegal. We'll issue an error during
+ relocate_section. */
+ default:
+ return 0;
+ }
+ }
+
/* Work out the sizes of the dynamic relocation entries. */
static boolean
*************** elf64_alpha_calc_dynrel_sizes (h, info)
*** 3044,3049 ****
--- 3373,3383 ----
struct alpha_elf_link_hash_entry *h;
struct bfd_link_info *info;
{
+ boolean dynamic;
+ struct alpha_elf_reloc_entry *relent;
+ struct alpha_elf_got_entry *gotent;
+ int entries;
+
if (h->root.root.type == bfd_link_hash_warning)
h = (struct alpha_elf_link_hash_entry *) h->root.root.u.i.link;
*************** elf64_alpha_calc_dynrel_sizes (h, info)
*** 3070,3110 ****
natural form. If this is a shared object, and it has been forced
local, we'll need the same number of RELATIVE relocations. */
! if (alpha_elf_dynamic_symbol_p (&h->root, info) || info->shared)
! {
! struct alpha_elf_reloc_entry *relent;
! bfd *dynobj;
! struct alpha_elf_got_entry *gotent;
! bfd_size_type count;
! asection *srel;
!
! for (relent = h->reloc_entries; relent; relent = relent->next)
! if (relent->rtype == R_ALPHA_REFLONG
! || relent->rtype == R_ALPHA_REFQUAD)
! {
! relent->srel->_raw_size +=
! sizeof (Elf64_External_Rela) * relent->count;
! if (relent->reltext)
! info->flags |= DT_TEXTREL;
! }
! dynobj = elf_hash_table(info)->dynobj;
! count = 0;
! for (gotent = h->got_entries; gotent ; gotent = gotent->next)
! count++;
! /* If we are using a .plt entry, subtract one, as the first
! reference uses a .rela.plt entry instead. */
! if (h->root.plt.offset != MINUS_ONE)
! count--;
! if (count > 0)
! {
! srel = bfd_get_section_by_name (dynobj, ".rela.got");
! BFD_ASSERT (srel != NULL);
! srel->_raw_size += sizeof (Elf64_External_Rela) * count;
! }
}
return true;
--- 3404,3440 ----
natural form. If this is a shared object, and it has been forced
local, we'll need the same number of RELATIVE relocations. */
! dynamic = alpha_elf_dynamic_symbol_p (&h->root, info);
! for (relent = h->reloc_entries; relent; relent = relent->next)
! {
! entries = alpha_dynamic_entries_for_reloc (relent->rtype, dynamic,
! info->shared);
! if (entries)
! {
! relent->srel->_raw_size +=
! entries * sizeof (Elf64_External_Rela) * relent->count;
! if (relent->reltext)
! info->flags |= DT_TEXTREL;
! }
! }
! entries = 0;
! for (gotent = h->got_entries; gotent ; gotent = gotent->next)
! entries += alpha_dynamic_entries_for_reloc (gotent->reloc_type,
! dynamic, info->shared);
! /* If we are using a .plt entry, subtract one, as the first
! reference uses a .rela.plt entry instead. */
! if (h->root.plt.offset != MINUS_ONE)
! entries--;
! if (entries > 0)
! {
! bfd *dynobj = elf_hash_table(info)->dynobj;
! asection *srel = bfd_get_section_by_name (dynobj, ".rela.got");
! BFD_ASSERT (srel != NULL);
! srel->_raw_size += sizeof (Elf64_External_Rela) * entries;
}
return true;
*************** elf64_alpha_size_dynamic_sections (outpu
*** 3126,3131 ****
--- 3456,3464 ----
if (elf_hash_table (info)->dynamic_sections_created)
{
+ int entries;
+ bfd *i;
+
/* Set the contents of the .interp section to the interpreter. */
if (!info->shared)
{
*************** elf64_alpha_size_dynamic_sections (outpu
*** 3143,3165 ****
elf64_alpha_calc_dynrel_sizes,
info);
! /* When building shared libraries, each local .got entry needs a
! RELATIVE reloc. */
! if (info->shared)
{
! bfd *i;
! asection *srel;
! bfd_size_type count;
! srel = bfd_get_section_by_name (dynobj, ".rela.got");
! BFD_ASSERT (srel != NULL);
! for (i = alpha_elf_hash_table(info)->got_list, count = 0;
! i != NULL;
! i = alpha_elf_tdata(i)->got_link_next)
! count += alpha_elf_tdata(i)->n_local_got_entries;
! srel->_raw_size += count * sizeof (Elf64_External_Rela);
}
}
/* else we're not dynamic and by definition we don't need such things. */
--- 3476,3513 ----
elf64_alpha_calc_dynrel_sizes,
info);
! /* Shared libraries often require RELATIVE relocs, and some relocs
! require attention for the main application as well. */
!
! entries = 0;
! for (i = alpha_elf_hash_table(info)->got_list;
! i ; i = alpha_elf_tdata(i)->got_link_next)
{
! bfd *j;
! for (j = i; j ; j = alpha_elf_tdata(j)->in_got_link_next)
! {
! struct alpha_elf_got_entry **local_got_entries, *gotent;
! int k, n;
! local_got_entries = alpha_elf_tdata(j)->local_got_entries;
! if (!local_got_entries)
! continue;
! for (k = 0, n = elf_tdata(j)->symtab_hdr.sh_info; k < n; ++k)
! for (gotent = local_got_entries[k];
! gotent ; gotent = gotent->next)
! if (gotent->use_count > 0)
! entries += (alpha_dynamic_entries_for_reloc
! (gotent->reloc_type, 0, info->shared));
! }
! }
!
! if (entries > 0)
! {
! s = bfd_get_section_by_name (dynobj, ".rela.got");
! BFD_ASSERT (s != NULL);
! s->_raw_size += sizeof (Elf64_External_Rela) * entries;
}
}
/* else we're not dynamic and by definition we don't need such things. */
*************** elf64_alpha_relocate_section (output_bfd
*** 3278,3337 ****
Elf_Internal_Sym *local_syms;
asection **local_sections;
{
! Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
! asection *sec, *sgot, *srel, *srelgot;
! bfd *dynobj, *gotobj;
! bfd_vma gp;
boolean ret_val = true;
! srelgot = srel = NULL;
! symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
! dynobj = elf_hash_table (info)->dynobj;
! if (dynobj)
{
! srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
! }
! /* Find the gp value for this input bfd. */
! sgot = NULL;
! gp = 0;
! gotobj = alpha_elf_tdata (input_bfd)->gotobj;
! if (gotobj)
! {
! sgot = alpha_elf_tdata (gotobj)->got;
! gp = _bfd_get_gp_value (gotobj);
! if (gp == 0)
{
! gp = (sgot->output_section->vma
! + sgot->output_offset
! + 0x8000);
! _bfd_set_gp_value (gotobj, gp);
! }
}
rel = relocs;
relend = relocs + input_section->reloc_count;
for (; rel < relend; rel++)
{
! int r_type;
reloc_howto_type *howto;
unsigned long r_symndx;
- struct alpha_elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
! bfd_vma relocation;
bfd_vma addend;
! bfd_reloc_status_type r;
r_type = ELF64_R_TYPE(rel->r_info);
! if (r_type < 0 || r_type >= (int) R_ALPHA_max)
{
bfd_set_error (bfd_error_bad_value);
! return false;
}
- howto = elf64_alpha_howto_table + r_type;
r_symndx = ELF64_R_SYM(rel->r_info);
if (info->relocateable)
--- 3626,3710 ----
Elf_Internal_Sym *local_syms;
asection **local_sections;
{
! Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
! struct elf_link_tls_segment *tls_segment = NULL;
! asection *sgot = NULL, *srel = NULL, *srelgot = NULL;
! bfd *dynobj = NULL, *gotobj = NULL;
! bfd_vma gp = 0, tp_base = 0, dtp_base = 0;
boolean ret_val = true;
! if (!info->relocateable)
{
! const char *name;
! dynobj = elf_hash_table (info)->dynobj;
! if (dynobj)
! srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
!
! name = (bfd_elf_string_from_elf_section
! (input_bfd, elf_elfheader(input_bfd)->e_shstrndx,
! elf_section_data(input_section)->rel_hdr.sh_name));
! BFD_ASSERT(name != NULL);
! srel = bfd_get_section_by_name (dynobj, name);
!
! /* Find the gp value for this input bfd. */
! gotobj = alpha_elf_tdata (input_bfd)->gotobj;
! if (gotobj)
{
! sgot = alpha_elf_tdata (gotobj)->got;
! gp = _bfd_get_gp_value (gotobj);
! if (gp == 0)
! {
! gp = (sgot->output_section->vma
! + sgot->output_offset
! + 0x8000);
! _bfd_set_gp_value (gotobj, gp);
! }
! }
!
! tls_segment = elf_hash_table (info)->tls_segment;
! if (tls_segment)
! {
! /* This is PT_TLS segment p_vaddr. */
! dtp_base = tls_segment->start;
!
! /* Main program TLS (whose template starts at PT_TLS p_vaddr)
! is assigned offset round(16, PT_TLS p_align). */
! tp_base = dtp_base - align_power (16, tls_segment->align);
! }
}
rel = relocs;
relend = relocs + input_section->reloc_count;
for (; rel < relend; rel++)
{
! struct alpha_elf_link_hash_entry *h;
! struct alpha_elf_got_entry *gotent;
! bfd_reloc_status_type r;
reloc_howto_type *howto;
unsigned long r_symndx;
Elf_Internal_Sym *sym;
! asection *sec;
! bfd_vma value;
bfd_vma addend;
! boolean dynamic_symbol_p;
! boolean undef_weak_ref;
! unsigned long r_type;
r_type = ELF64_R_TYPE(rel->r_info);
! if (r_type >= R_ALPHA_max)
{
+ (*_bfd_error_handler)
+ (_("%s: unknown relocation type %d"),
+ bfd_archive_filename (input_bfd), (int)r_type);
bfd_set_error (bfd_error_bad_value);
! ret_val = false;
! continue;
}
+ howto = elf64_alpha_howto_table + r_type;
r_symndx = ELF64_R_SYM(rel->r_info);
if (info->relocateable)
*************** elf64_alpha_relocate_section (output_bfd
*** 3364,3375 ****
h = NULL;
sym = NULL;
sec = NULL;
if (r_symndx < symtab_hdr->sh_info)
{
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
! relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
}
else
{
--- 3737,3784 ----
h = NULL;
sym = NULL;
sec = NULL;
+ undef_weak_ref = false;
if (r_symndx < symtab_hdr->sh_info)
{
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
! value = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
!
! gotent = alpha_elf_tdata(input_bfd)->local_got_entries[r_symndx];
!
! /* Need to adjust local GOT entries' addends for SEC_MERGE
! unless it has been done already. */
! if ((sec->flags & SEC_MERGE)
! && ELF_ST_TYPE (sym->st_info) == STT_SECTION
! && (elf_section_data (sec)->sec_info_type
! == ELF_INFO_TYPE_MERGE)
! && !gotent->reloc_xlated)
! {
! struct alpha_elf_got_entry *ent;
! asection *msec;
!
! for (ent = gotent; ent; ent = ent->next)
! {
! ent->reloc_xlated = 1;
! if (ent->use_count == 0)
! continue;
! msec = sec;
! ent->addend =
! _bfd_merged_section_offset (output_bfd, &msec,
! elf_section_data (sec)->
! sec_info,
! sym->st_value + ent->addend,
! (bfd_vma) 0);
! ent->addend -= sym->st_value;
! ent->addend += msec->output_section->vma
! + msec->output_offset
! - sec->output_section->vma
! - sec->output_offset;
! }
! }
!
! dynamic_symbol_p = false;
}
else
{
*************** elf64_alpha_relocate_section (output_bfd
*** 3379,3405 ****
|| h->root.root.type == bfd_link_hash_warning)
h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
if (h->root.root.type == bfd_link_hash_defined
|| h->root.root.type == bfd_link_hash_defweak)
{
sec = h->root.root.u.def.section;
! if (sec->output_section == NULL)
! relocation = 0;
! else
! {
! relocation = (h->root.root.u.def.value
! + sec->output_section->vma
! + sec->output_offset);
! }
}
else if (h->root.root.type == bfd_link_hash_undefweak)
! relocation = 0;
else if (info->shared
&& (!info->symbolic || info->allow_shlib_undefined)
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
! relocation = 0;
else
{
if (!((*info->callbacks->undefined_symbol)
--- 3788,3819 ----
|| h->root.root.type == bfd_link_hash_warning)
h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
+ value = 0;
if (h->root.root.type == bfd_link_hash_defined
|| h->root.root.type == bfd_link_hash_defweak)
{
sec = h->root.root.u.def.section;
! /* Detect the cases that sym_sec->output_section is
! expected to be NULL -- all cases in which the symbol
! is defined in another shared module. This includes
! PLT relocs for which we've created a PLT entry and
! other relocs for which we're prepared to create
! dynamic relocations. */
! /* ??? Just accept it NULL and continue. */
!
! if (sec->output_section != NULL)
! value = (h->root.root.u.def.value
! + sec->output_section->vma
! + sec->output_offset);
}
else if (h->root.root.type == bfd_link_hash_undefweak)
! undef_weak_ref = true;
else if (info->shared
&& (!info->symbolic || info->allow_shlib_undefined)
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
! ;
else
{
if (!((*info->callbacks->undefined_symbol)
*************** elf64_alpha_relocate_section (output_bfd
*** 3407,3417 ****
input_section, rel->r_offset,
(!info->shared || info->no_undefined
|| ELF_ST_VISIBILITY (h->root.other)))))
! ret_val = false;
! relocation = 0;
}
}
addend = rel->r_addend;
switch (r_type)
{
--- 3821,3844 ----
input_section, rel->r_offset,
(!info->shared || info->no_undefined
|| ELF_ST_VISIBILITY (h->root.other)))))
! return false;
! ret_val = false;
! continue;
}
+
+ dynamic_symbol_p = alpha_elf_dynamic_symbol_p (&h->root, info);
+ gotent = h->got_entries;
}
+
addend = rel->r_addend;
+ value += addend;
+
+ /* Search for the proper got entry. */
+ for (; gotent ; gotent = gotent->next)
+ if (gotent->gotobj == gotobj
+ && gotent->reloc_type == r_type
+ && gotent->addend == addend)
+ break;
switch (r_type)
{
*************** elf64_alpha_relocate_section (output_bfd
*** 3421,3544 ****
BFD_ASSERT(gp != 0);
! relocation = (input_section->output_section->vma
! + input_section->output_offset
! + rel->r_offset);
! p_ldah = contents + rel->r_offset - input_section->vma;
p_lda = p_ldah + rel->r_addend;
! r = elf64_alpha_do_reloc_gpdisp (input_bfd, gp - relocation,
p_ldah, p_lda);
}
break;
case R_ALPHA_LITERAL:
! {
! struct alpha_elf_got_entry *gotent;
! boolean dynamic_symbol;
!
! BFD_ASSERT(sgot != NULL);
! BFD_ASSERT(gp != 0);
!
! if (h != NULL)
! {
! gotent = h->got_entries;
! dynamic_symbol = alpha_elf_dynamic_symbol_p (&h->root, info);
! }
! else
! {
! gotent = (alpha_elf_tdata(input_bfd)->
! local_got_entries[r_symndx]);
! dynamic_symbol = false;
!
! /* Need to adjust local GOT entries' addends for SEC_MERGE
! unless it has been done already. */
! if ((sec->flags & SEC_MERGE)
! && ELF_ST_TYPE (sym->st_info) == STT_SECTION
! && (elf_section_data (sec)->sec_info_type
! == ELF_INFO_TYPE_MERGE)
! && (gotent->flags & ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED) == 0)
! {
! struct alpha_elf_got_entry *ent;
! asection *msec;
!
! for (ent = gotent; ent; ent = ent->next)
! {
! ent->flags |= ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED;
! if (ent->use_count == 0)
! continue;
! msec = sec;
! ent->addend =
! _bfd_merged_section_offset (output_bfd, &msec,
! elf_section_data (sec)->
! sec_info,
! sym->st_value
! + ent->addend,
! (bfd_vma) 0);
! ent->addend -= sym->st_value;
! ent->addend += msec->output_section->vma
! + msec->output_offset
! - sec->output_section->vma
! - sec->output_offset;
! }
! }
! }
!
! BFD_ASSERT(gotent != NULL);
!
! while (gotent->gotobj != gotobj || gotent->addend != addend)
! gotent = gotent->next;
!
! BFD_ASSERT(gotent->use_count >= 1);
! /* Initialize the .got entry's value. */
! if (!(gotent->flags & ALPHA_ELF_GOT_ENTRY_RELOCS_DONE))
! {
! bfd_put_64 (output_bfd, relocation + addend,
! sgot->contents + gotent->got_offset);
! /* If the symbol has been forced local, output a
! RELATIVE reloc, otherwise it will be handled in
! finish_dynamic_symbol. */
! if (info->shared && !dynamic_symbol)
! {
! Elf_Internal_Rela outrel;
! BFD_ASSERT(srelgot != NULL);
! outrel.r_offset = (sgot->output_section->vma
! + sgot->output_offset
! + gotent->got_offset);
! outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE);
! outrel.r_addend = relocation + addend;
! bfd_elf64_swap_reloca_out (output_bfd, &outrel,
! ((Elf64_External_Rela *)
! srelgot->contents)
! + srelgot->reloc_count++);
! BFD_ASSERT (sizeof (Elf64_External_Rela)
! * srelgot->reloc_count
! <= srelgot->_cooked_size);
! }
! gotent->flags |= ALPHA_ELF_GOT_ENTRY_RELOCS_DONE;
! }
! /* Figure the gprel relocation. */
! addend = 0;
! relocation = (sgot->output_section->vma
! + sgot->output_offset
! + gotent->got_offset);
! relocation -= gp;
! }
! /* overflow handled by _bfd_final_link_relocate */
goto default_reloc;
case R_ALPHA_GPREL16:
case R_ALPHA_GPREL32:
case R_ALPHA_GPRELLOW:
! if (h && alpha_elf_dynamic_symbol_p (&h->root, info))
{
(*_bfd_error_handler)
(_("%s: gp-relative relocation against dynamic symbol %s"),
--- 3848,3913 ----
BFD_ASSERT(gp != 0);
! value = (input_section->output_section->vma
! + input_section->output_offset
! + rel->r_offset);
! p_ldah = contents + rel->r_offset;
p_lda = p_ldah + rel->r_addend;
! r = elf64_alpha_do_reloc_gpdisp (input_bfd, gp - value,
p_ldah, p_lda);
}
break;
case R_ALPHA_LITERAL:
! BFD_ASSERT(sgot != NULL);
! BFD_ASSERT(gp != 0);
! BFD_ASSERT(gotent != NULL);
! BFD_ASSERT(gotent->use_count >= 1);
! if (!gotent->reloc_done)
! {
! gotent->reloc_done = 1;
! bfd_put_64 (output_bfd, value,
! sgot->contents + gotent->got_offset);
! /* If the symbol has been forced local, output a
! RELATIVE reloc, otherwise it will be handled in
! finish_dynamic_symbol. */
! if (info->shared && !dynamic_symbol_p)
! {
! Elf_Internal_Rela outrel;
! BFD_ASSERT(srelgot != NULL);
! outrel.r_offset = (sgot->output_section->vma
! + sgot->output_offset
! + gotent->got_offset);
! outrel.r_info = ELF64_R_INFO (0, R_ALPHA_RELATIVE);
! outrel.r_addend = value;
! bfd_elf64_swap_reloca_out (output_bfd, &outrel,
! ((Elf64_External_Rela *)
! srelgot->contents)
! + srelgot->reloc_count++);
! BFD_ASSERT (sizeof (Elf64_External_Rela)
! * srelgot->reloc_count
! <= srelgot->_cooked_size);
! }
! }
! value = (sgot->output_section->vma
! + sgot->output_offset
! + gotent->got_offset);
! value -= gp;
goto default_reloc;
case R_ALPHA_GPREL16:
case R_ALPHA_GPREL32:
case R_ALPHA_GPRELLOW:
! if (dynamic_symbol_p)
{
(*_bfd_error_handler)
(_("%s: gp-relative relocation against dynamic symbol %s"),
*************** elf64_alpha_relocate_section (output_bfd
*** 3546,3556 ****
ret_val = false;
}
BFD_ASSERT(gp != 0);
! relocation -= gp;
goto default_reloc;
case R_ALPHA_GPRELHIGH:
! if (h && alpha_elf_dynamic_symbol_p (&h->root, info))
{
(*_bfd_error_handler)
(_("%s: gp-relative relocation against dynamic symbol %s"),
--- 3915,3925 ----
ret_val = false;
}
BFD_ASSERT(gp != 0);
! value -= gp;
goto default_reloc;
case R_ALPHA_GPRELHIGH:
! if (dynamic_symbol_p)
{
(*_bfd_error_handler)
(_("%s: gp-relative relocation against dynamic symbol %s"),
*************** elf64_alpha_relocate_section (output_bfd
*** 3558,3584 ****
ret_val = false;
}
BFD_ASSERT(gp != 0);
! relocation -= gp;
! relocation += addend;
! addend = 0;
! relocation = (((bfd_signed_vma) relocation >> 16)
! + ((relocation >> 15) & 1));
goto default_reloc;
case R_ALPHA_HINT:
/* A call to a dynamic symbol is definitely out of range of
the 16-bit displacement. Don't bother writing anything. */
! if (h && alpha_elf_dynamic_symbol_p (&h->root, info))
{
r = bfd_reloc_ok;
break;
}
! /* FALLTHRU */
case R_ALPHA_BRADDR:
/* The regular PC-relative stuff measures from the start of
the instruction rather than the end. */
! addend -= 4;
goto default_reloc;
case R_ALPHA_BRSGP:
--- 3927,3960 ----
ret_val = false;
}
BFD_ASSERT(gp != 0);
! value -= gp;
! value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
goto default_reloc;
case R_ALPHA_HINT:
/* A call to a dynamic symbol is definitely out of range of
the 16-bit displacement. Don't bother writing anything. */
! if (dynamic_symbol_p)
{
r = bfd_reloc_ok;
break;
}
! /* The regular PC-relative stuff measures from the start of
! the instruction rather than the end. */
! value -= 4;
! goto default_reloc;
case R_ALPHA_BRADDR:
+ if (dynamic_symbol_p)
+ {
+ (*_bfd_error_handler)
+ (_("%s: pc-relative relocation against dynamic symbol %s"),
+ bfd_archive_filename (input_bfd), h->root.root.root.string);
+ ret_val = false;
+ }
/* The regular PC-relative stuff measures from the start of
the instruction rather than the end. */
! value -= 4;
goto default_reloc;
case R_ALPHA_BRSGP:
*************** elf64_alpha_relocate_section (output_bfd
*** 3588,3594 ****
/* The regular PC-relative stuff measures from the start of
the instruction rather than the end. */
! addend -= 4;
/* The source and destination gp must be the same. Note that
the source will always have an assigned gp, since we forced
--- 3964,3970 ----
/* The regular PC-relative stuff measures from the start of
the instruction rather than the end. */
! value -= 4;
/* The source and destination gp must be the same. Note that
the source will always have an assigned gp, since we forced
*************** elf64_alpha_relocate_section (output_bfd
*** 3641,3681 ****
case R_ALPHA_REFLONG:
case R_ALPHA_REFQUAD:
{
Elf_Internal_Rela outrel;
/* Careful here to remember RELATIVE relocations for global
variables for symbolic shared objects. */
! if (h && alpha_elf_dynamic_symbol_p (&h->root, info))
{
BFD_ASSERT(h->root.dynindx != -1);
! outrel.r_info = ELF64_R_INFO(h->root.dynindx, r_type);
outrel.r_addend = addend;
! addend = 0, relocation = 0;
}
else if (info->shared
&& r_symndx != 0
&& (input_section->flags & SEC_ALLOC))
{
! outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE);
! outrel.r_addend = relocation + addend;
}
else
goto default_reloc;
! if (!srel)
! {
! const char *name;
!
! name = (bfd_elf_string_from_elf_section
! (input_bfd, elf_elfheader(input_bfd)->e_shstrndx,
! elf_section_data(input_section)->rel_hdr.sh_name));
! BFD_ASSERT(name != NULL);
!
! srel = bfd_get_section_by_name (dynobj, name);
! BFD_ASSERT(srel != NULL);
! }
outrel.r_offset =
_bfd_elf_section_offset (output_bfd, info, input_section,
--- 4017,4068 ----
case R_ALPHA_REFLONG:
case R_ALPHA_REFQUAD:
+ case R_ALPHA_DTPREL64:
+ case R_ALPHA_TPREL64:
{
Elf_Internal_Rela outrel;
/* Careful here to remember RELATIVE relocations for global
variables for symbolic shared objects. */
! if (dynamic_symbol_p)
{
BFD_ASSERT(h->root.dynindx != -1);
! outrel.r_info = ELF64_R_INFO (h->root.dynindx, r_type);
outrel.r_addend = addend;
! addend = 0, value = 0;
! }
! else if (r_type == R_ALPHA_DTPREL64)
! {
! BFD_ASSERT(tls_segment != NULL);
! value -= dtp_base;
! goto default_reloc;
! }
! else if (r_type == R_ALPHA_TPREL64)
! {
! BFD_ASSERT(tls_segment != NULL);
! value -= dtp_base;
! goto default_reloc;
}
else if (info->shared
&& r_symndx != 0
&& (input_section->flags & SEC_ALLOC))
{
! if (r_type == R_ALPHA_REFLONG)
! {
! (*_bfd_error_handler)
! (_("%s: unhandled dynamic relocation against %s"),
! bfd_archive_filename (input_bfd),
! h->root.root.root.string);
! ret_val = false;
! }
! outrel.r_info = ELF64_R_INFO (0, R_ALPHA_RELATIVE);
! outrel.r_addend = value;
}
else
goto default_reloc;
! BFD_ASSERT(srel != NULL);
outrel.r_offset =
_bfd_elf_section_offset (output_bfd, info, input_section,
*************** elf64_alpha_relocate_section (output_bfd
*** 3695,3702 ****
--- 4082,4098 ----
}
goto default_reloc;
+ case R_ALPHA_SREL16:
case R_ALPHA_SREL32:
case R_ALPHA_SREL64:
+ if (dynamic_symbol_p)
+ {
+ (*_bfd_error_handler)
+ (_("%s: pc-relative relocation against dynamic symbol %s"),
+ bfd_archive_filename (input_bfd), h->root.root.root.string);
+ ret_val = false;
+ }
+
/* ??? .eh_frame references to discarded sections will be smashed
to relocations against SHN_UNDEF. The .eh_frame format allows
NULL to be encoded as 0 in any format, so this works here. */
*************** elf64_alpha_relocate_section (output_bfd
*** 3705,3715 ****
+ (r_type - R_ALPHA_SREL32 + R_ALPHA_REFLONG));
goto default_reloc;
default:
default_reloc:
r = _bfd_final_link_relocate (howto, input_bfd, input_section,
! contents, rel->r_offset, relocation,
! addend);
break;
}
--- 4101,4223 ----
+ (r_type - R_ALPHA_SREL32 + R_ALPHA_REFLONG));
goto default_reloc;
+ case R_ALPHA_TLSLDM:
+ /* Ignore the symbol for the relocation. The result is always
+ the current module. */
+ dynamic_symbol_p = 0;
+ /* FALLTHRU */
+
+ case R_ALPHA_TLSGD:
+ if (!gotent->reloc_done)
+ {
+ gotent->reloc_done = 1;
+
+ /* Note that the module index for the main program is 1. */
+ bfd_put_64 (output_bfd, !info->shared && !dynamic_symbol_p,
+ sgot->contents + gotent->got_offset);
+
+ /* If the symbol has been forced local, output a
+ DTPMOD64 reloc, otherwise it will be handled in
+ finish_dynamic_symbol. */
+ if (info->shared && !dynamic_symbol_p)
+ {
+ Elf_Internal_Rela outrel;
+
+ BFD_ASSERT(srelgot != NULL);
+
+ outrel.r_offset = (sgot->output_section->vma
+ + sgot->output_offset
+ + gotent->got_offset);
+ /* ??? Proper dynindx here. */
+ outrel.r_info = ELF64_R_INFO (0, R_ALPHA_DTPMOD64);
+ outrel.r_addend = 0;
+
+ bfd_elf64_swap_reloca_out (output_bfd, &outrel,
+ ((Elf64_External_Rela *)
+ srelgot->contents)
+ + srelgot->reloc_count++);
+ BFD_ASSERT (sizeof (Elf64_External_Rela)
+ * srelgot->reloc_count
+ <= srelgot->_cooked_size);
+ }
+
+ if (dynamic_symbol_p || r_type == R_ALPHA_TLSLDM)
+ value = 0;
+ else
+ {
+ BFD_ASSERT(tls_segment != NULL);
+ value -= dtp_base;
+ }
+ bfd_put_64 (output_bfd, value,
+ sgot->contents + gotent->got_offset + 8);
+ }
+
+ value = (sgot->output_section->vma
+ + sgot->output_offset
+ + gotent->got_offset);
+ value -= gp;
+ goto default_reloc;
+
+ case R_ALPHA_DTPRELHI:
+ case R_ALPHA_DTPRELLO:
+ case R_ALPHA_DTPREL16:
+ if (dynamic_symbol_p)
+ {
+ (*_bfd_error_handler)
+ (_("%s: dtp-relative relocation against dynamic symbol %s"),
+ bfd_archive_filename (input_bfd), h->root.root.root.string);
+ ret_val = false;
+ }
+ BFD_ASSERT(tls_segment != NULL);
+ value -= dtp_base;
+ goto default_reloc;
+
+ case R_ALPHA_TPRELHI:
+ case R_ALPHA_TPRELLO:
+ case R_ALPHA_TPREL16:
+ if (dynamic_symbol_p)
+ {
+ (*_bfd_error_handler)
+ (_("%s: tp-relative relocation against dynamic symbol %s"),
+ bfd_archive_filename (input_bfd), h->root.root.root.string);
+ ret_val = false;
+ }
+ BFD_ASSERT(tls_segment != NULL);
+ value -= tp_base;
+ goto default_reloc;
+
+ case R_ALPHA_GOTDTPREL:
+ case R_ALPHA_GOTTPREL:
+ BFD_ASSERT(sgot != NULL);
+ BFD_ASSERT(gp != 0);
+ BFD_ASSERT(gotent != NULL);
+ BFD_ASSERT(gotent->use_count >= 1);
+
+ if (!gotent->reloc_done)
+ {
+ gotent->reloc_done = 1;
+
+ if (dynamic_symbol_p)
+ value = 0;
+ else
+ {
+ BFD_ASSERT(tls_segment != NULL);
+ value -= (r_type == R_ALPHA_GOTDTPREL ? dtp_base : tp_base);
+ }
+ bfd_put_64 (output_bfd, value,
+ sgot->contents + gotent->got_offset);
+ }
+
+ value = (sgot->output_section->vma
+ + sgot->output_offset
+ + gotent->got_offset);
+ value -= gp;
+ goto default_reloc;
+
default:
default_reloc:
r = _bfd_final_link_relocate (howto, input_bfd, input_section,
! contents, rel->r_offset, value, 0);
break;
}
*************** elf64_alpha_finish_dynamic_symbol (outpu
*** 3881,3900 ****
srel = bfd_get_section_by_name (dynobj, ".rela.got");
BFD_ASSERT (srel != NULL);
- outrel.r_info = ELF64_R_INFO (h->dynindx, R_ALPHA_GLOB_DAT);
for (gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries;
gotent != NULL;
gotent = gotent->next)
{
asection *sgot = alpha_elf_tdata (gotent->gotobj)->got;
outrel.r_offset = (sgot->output_section->vma
+ sgot->output_offset
+ gotent->got_offset);
outrel.r_addend = gotent->addend;
bfd_elf64_swap_reloca_out (output_bfd, &outrel,
((Elf64_External_Rela *)srel->contents
+ srel->reloc_count++));
BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
<= srel->_cooked_size);
}
--- 4389,4442 ----
srel = bfd_get_section_by_name (dynobj, ".rela.got");
BFD_ASSERT (srel != NULL);
for (gotent = ((struct alpha_elf_link_hash_entry *) h)->got_entries;
gotent != NULL;
gotent = gotent->next)
{
asection *sgot = alpha_elf_tdata (gotent->gotobj)->got;
+ int r_type;
+
outrel.r_offset = (sgot->output_section->vma
+ sgot->output_offset
+ gotent->got_offset);
+
+ r_type = gotent->reloc_type;
+ switch (r_type)
+ {
+ case R_ALPHA_LITERAL:
+ r_type = R_ALPHA_GLOB_DAT;
+ break;
+ case R_ALPHA_TLSGD:
+ r_type = R_ALPHA_DTPMOD64;
+ break;
+ case R_ALPHA_GOTDTPREL:
+ r_type = R_ALPHA_DTPREL64;
+ break;
+ case R_ALPHA_GOTTPREL:
+ r_type = R_ALPHA_TPREL64;
+ break;
+ case R_ALPHA_TLSLDM:
+ default:
+ abort ();
+ }
+
+ outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
outrel.r_addend = gotent->addend;
bfd_elf64_swap_reloca_out (output_bfd, &outrel,
((Elf64_External_Rela *)srel->contents
+ srel->reloc_count++));
+
+ if (gotent->reloc_type == R_ALPHA_TLSGD)
+ {
+ outrel.r_offset += 8;
+ outrel.r_info = ELF64_R_INFO (h->dynindx, R_ALPHA_DTPREL64);
+
+ bfd_elf64_swap_reloca_out (output_bfd, &outrel,
+ ((Elf64_External_Rela *)srel->contents
+ + srel->reloc_count++));
+ }
+
BFD_ASSERT (sizeof (Elf64_External_Rela) * srel->reloc_count
<= srel->_cooked_size);
}
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/src/src/bfd/reloc.c,v
retrieving revision 1.59
diff -c -p -d -r1.59 reloc.c
*** bfd/reloc.c 30 May 2002 02:14:13 -0000 1.59
--- bfd/reloc.c 30 May 2002 21:41:27 -0000
*************** ENUMDOC
*** 1963,1968 ****
--- 1963,1997 ----
STO_ALPHA_STD_GPLOAD.
ENUM
+ BFD_RELOC_ALPHA_TLSGD
+ ENUMX
+ BFD_RELOC_ALPHA_TLSLDM
+ ENUMX
+ BFD_RELOC_ALPHA_DTPMOD64
+ ENUMX
+ BFD_RELOC_ALPHA_GOTDTPREL16
+ ENUMX
+ BFD_RELOC_ALPHA_DTPREL64
+ ENUMX
+ BFD_RELOC_ALPHA_DTPREL_HI16
+ ENUMX
+ BFD_RELOC_ALPHA_DTPREL_LO16
+ ENUMX
+ BFD_RELOC_ALPHA_DTPREL16
+ ENUMX
+ BFD_RELOC_ALPHA_GOTTPREL16
+ ENUMX
+ BFD_RELOC_ALPHA_TPREL64
+ ENUMX
+ BFD_RELOC_ALPHA_TPREL_HI16
+ ENUMX
+ BFD_RELOC_ALPHA_TPREL_LO16
+ ENUMX
+ BFD_RELOC_ALPHA_TPREL16
+ ENUMDOC
+ Alpha thread-local storage relocations.
+
+ ENUM
BFD_RELOC_MIPS_JMP
ENUMDOC
Bits 27..2 of the relocation address shifted right 2 bits;
Index: gas/expr.h
===================================================================
RCS file: /cvs/src/src/gas/expr.h,v
retrieving revision 1.10
diff -c -p -d -r1.10 expr.h
*** gas/expr.h 8 Mar 2001 23:24:22 -0000 1.10
--- gas/expr.h 30 May 2002 21:41:27 -0000
*************** typedef enum {
*** 107,112 ****
--- 107,114 ----
/* machine dependent operators */
O_md1, O_md2, O_md3, O_md4, O_md5, O_md6, O_md7, O_md8,
O_md9, O_md10, O_md11, O_md12, O_md13, O_md14, O_md15, O_md16,
+ O_md17, O_md18, O_md19, O_md20, O_md21, O_md22, O_md23, O_md24,
+ O_md25, O_md26, O_md27, O_md28, O_md29, O_md30, O_md31, O_md32,
/* this must be the largest value */
O_max
} operatorT;
Index: gas/config/tc-alpha.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-alpha.c,v
retrieving revision 1.41
diff -c -p -d -r1.41 tc-alpha.c
*** gas/config/tc-alpha.c 23 May 2002 13:12:48 -0000 1.41
--- gas/config/tc-alpha.c 30 May 2002 21:41:27 -0000
*************** struct alpha_macro {
*** 106,135 ****
#define O_pregister O_md1 /* O_register, in parentheses */
#define O_cpregister O_md2 /* + a leading comma */
! /* Note, the alpha_reloc_op table below depends on the ordering
! of O_literal .. O_gpre16. */
#define O_literal O_md3 /* !literal relocation */
#define O_lituse_addr O_md4 /* !lituse_addr relocation */
#define O_lituse_base O_md5 /* !lituse_base relocation */
#define O_lituse_bytoff O_md6 /* !lituse_bytoff relocation */
#define O_lituse_jsr O_md7 /* !lituse_jsr relocation */
! #define O_gpdisp O_md8 /* !gpdisp relocation */
! #define O_gprelhigh O_md9 /* !gprelhigh relocation */
! #define O_gprellow O_md10 /* !gprellow relocation */
! #define O_gprel O_md11 /* !gprel relocation */
! #define O_samegp O_md12 /* !samegp relocation */
#define DUMMY_RELOC_LITUSE_ADDR (BFD_RELOC_UNUSED + 1)
#define DUMMY_RELOC_LITUSE_BASE (BFD_RELOC_UNUSED + 2)
#define DUMMY_RELOC_LITUSE_BYTOFF (BFD_RELOC_UNUSED + 3)
#define DUMMY_RELOC_LITUSE_JSR (BFD_RELOC_UNUSED + 4)
#define LITUSE_ADDR 0
#define LITUSE_BASE 1
#define LITUSE_BYTOFF 2
#define LITUSE_JSR 3
! #define USER_RELOC_P(R) ((R) >= O_literal && (R) <= O_samegp)
/* Macros for extracting the type and number of encoded register tokens */
--- 106,150 ----
#define O_pregister O_md1 /* O_register, in parentheses */
#define O_cpregister O_md2 /* + a leading comma */
! /* The alpha_reloc_op table below depends on the ordering of these. */
#define O_literal O_md3 /* !literal relocation */
#define O_lituse_addr O_md4 /* !lituse_addr relocation */
#define O_lituse_base O_md5 /* !lituse_base relocation */
#define O_lituse_bytoff O_md6 /* !lituse_bytoff relocation */
#define O_lituse_jsr O_md7 /* !lituse_jsr relocation */
! #define O_lituse_tlsgd O_md8 /* !lituse_tlsgd relocation */
! #define O_lituse_tlsldm O_md9 /* !lituse_tlsldm relocation */
! #define O_gpdisp O_md10 /* !gpdisp relocation */
! #define O_gprelhigh O_md11 /* !gprelhigh relocation */
! #define O_gprellow O_md12 /* !gprellow relocation */
! #define O_gprel O_md13 /* !gprel relocation */
! #define O_samegp O_md14 /* !samegp relocation */
! #define O_tlsgd O_md15 /* !tlsgd relocation */
! #define O_tlsldm O_md16 /* !tlsldm relocation */
! #define O_gotdtprel O_md17 /* !gotdtprel relocation */
! #define O_dtprelhi O_md18 /* !dtprelhi relocation */
! #define O_dtprello O_md19 /* !dtprello relocation */
! #define O_dtprel O_md20 /* !dtprel relocation */
! #define O_gottprel O_md21 /* !gottprel relocation */
! #define O_tprelhi O_md22 /* !tprelhi relocation */
! #define O_tprello O_md23 /* !tprello relocation */
! #define O_tprel O_md24 /* !tprel relocation */
#define DUMMY_RELOC_LITUSE_ADDR (BFD_RELOC_UNUSED + 1)
#define DUMMY_RELOC_LITUSE_BASE (BFD_RELOC_UNUSED + 2)
#define DUMMY_RELOC_LITUSE_BYTOFF (BFD_RELOC_UNUSED + 3)
#define DUMMY_RELOC_LITUSE_JSR (BFD_RELOC_UNUSED + 4)
+ #define DUMMY_RELOC_LITUSE_TLSGD (BFD_RELOC_UNUSED + 5)
+ #define DUMMY_RELOC_LITUSE_TLSLDM (BFD_RELOC_UNUSED + 6)
#define LITUSE_ADDR 0
#define LITUSE_BASE 1
#define LITUSE_BYTOFF 2
#define LITUSE_JSR 3
+ #define LITUSE_TLSGD 4
+ #define LITUSE_TLSLDM 5
! #define USER_RELOC_P(R) ((R) >= O_literal && (R) <= O_tprel)
/* Macros for extracting the type and number of encoded register tokens */
*************** static const struct alpha_reloc_op_tag {
*** 496,506 ****
DEF(lituse_base, DUMMY_RELOC_LITUSE_BASE, 1, 1),
DEF(lituse_bytoff, DUMMY_RELOC_LITUSE_BYTOFF, 1, 1),
DEF(lituse_jsr, DUMMY_RELOC_LITUSE_JSR, 1, 1),
DEF(gpdisp, BFD_RELOC_ALPHA_GPDISP, 1, 1),
DEF(gprelhigh, BFD_RELOC_ALPHA_GPREL_HI16, 0, 0),
DEF(gprellow, BFD_RELOC_ALPHA_GPREL_LO16, 0, 0),
DEF(gprel, BFD_RELOC_GPREL16, 0, 0),
! DEF(samegp, BFD_RELOC_ALPHA_BRSGP, 0, 0)
};
#undef DEF
--- 511,533 ----
DEF(lituse_base, DUMMY_RELOC_LITUSE_BASE, 1, 1),
DEF(lituse_bytoff, DUMMY_RELOC_LITUSE_BYTOFF, 1, 1),
DEF(lituse_jsr, DUMMY_RELOC_LITUSE_JSR, 1, 1),
+ DEF(lituse_tlsgd, DUMMY_RELOC_LITUSE_TLSGD, 1, 1),
+ DEF(lituse_tlsldm, DUMMY_RELOC_LITUSE_TLSLDM, 1, 1),
DEF(gpdisp, BFD_RELOC_ALPHA_GPDISP, 1, 1),
DEF(gprelhigh, BFD_RELOC_ALPHA_GPREL_HI16, 0, 0),
DEF(gprellow, BFD_RELOC_ALPHA_GPREL_LO16, 0, 0),
DEF(gprel, BFD_RELOC_GPREL16, 0, 0),
! DEF(samegp, BFD_RELOC_ALPHA_BRSGP, 0, 0),
! DEF(tlsgd, BFD_RELOC_ALPHA_TLSGD, 0, 1),
! DEF(tlsldm, BFD_RELOC_ALPHA_TLSLDM, 0, 1),
! DEF(gotdtprel, BFD_RELOC_ALPHA_GOTDTPREL16, 0, 0),
! DEF(dtprelhi, BFD_RELOC_ALPHA_DTPREL_HI16, 0, 0),
! DEF(dtprello, BFD_RELOC_ALPHA_DTPREL_LO16, 0, 0),
! DEF(dtprel, BFD_RELOC_ALPHA_DTPREL16, 0, 0),
! DEF(gottprel, BFD_RELOC_ALPHA_GOTTPREL16, 0, 0),
! DEF(tprelhi, BFD_RELOC_ALPHA_TPREL_HI16, 0, 0),
! DEF(tprello, BFD_RELOC_ALPHA_TPREL_LO16, 0, 0),
! DEF(tprel, BFD_RELOC_ALPHA_TPREL16, 0, 0),
};
#undef DEF
*************** static const int alpha_num_reloc_op
*** 515,526 ****
/* Structure to hold explict sequence information. */
struct alpha_reloc_tag
{
! fixS *slaves; /* head of linked list of !literals */
segT segment; /* segment relocs are in or undefined_section*/
long sequence; /* sequence # */
unsigned n_master; /* # of literals */
unsigned n_slaves; /* # of lituses */
! char multi_section_p; /* True if more than one section was used */
char string[1]; /* printable form of sequence to hash with */
};
--- 542,558 ----
/* Structure to hold explict sequence information. */
struct alpha_reloc_tag
{
! fixS *master; /* the literal reloc */
! fixS *slaves; /* head of linked list of lituses */
segT segment; /* segment relocs are in or undefined_section*/
long sequence; /* sequence # */
unsigned n_master; /* # of literals */
unsigned n_slaves; /* # of lituses */
! unsigned saw_tlsgd : 1; /* true if ... */
! unsigned saw_tlsldm : 1;
! unsigned saw_lu_tlsgd : 1;
! unsigned saw_lu_tlsldm : 1;
! unsigned multi_section_p : 1; /* true if more than one section was used */
char string[1]; /* printable form of sequence to hash with */
};
*************** md_apply_fix3 (fixP, valP, seg)
*** 1223,1228 ****
--- 1255,1270 ----
#ifdef OBJ_ELF
case BFD_RELOC_ALPHA_BRSGP:
+ case BFD_RELOC_ALPHA_TLSGD:
+ case BFD_RELOC_ALPHA_TLSLDM:
+ case BFD_RELOC_ALPHA_GOTDTPREL16:
+ case BFD_RELOC_ALPHA_DTPREL_HI16:
+ case BFD_RELOC_ALPHA_DTPREL_LO16:
+ case BFD_RELOC_ALPHA_DTPREL16:
+ case BFD_RELOC_ALPHA_GOTTPREL16:
+ case BFD_RELOC_ALPHA_TPREL_HI16:
+ case BFD_RELOC_ALPHA_TPREL_LO16:
+ case BFD_RELOC_ALPHA_TPREL16:
return;
#endif
*************** alpha_force_relocation (f)
*** 1441,1446 ****
--- 1483,1498 ----
case BFD_RELOC_ALPHA_BRSGP:
case BFD_RELOC_VTABLE_INHERIT:
case BFD_RELOC_VTABLE_ENTRY:
+ case BFD_RELOC_ALPHA_TLSGD:
+ case BFD_RELOC_ALPHA_TLSLDM:
+ case BFD_RELOC_ALPHA_GOTDTPREL16:
+ case BFD_RELOC_ALPHA_DTPREL_HI16:
+ case BFD_RELOC_ALPHA_DTPREL_LO16:
+ case BFD_RELOC_ALPHA_DTPREL16:
+ case BFD_RELOC_ALPHA_GOTTPREL16:
+ case BFD_RELOC_ALPHA_TPREL_HI16:
+ case BFD_RELOC_ALPHA_TPREL_LO16:
+ case BFD_RELOC_ALPHA_TPREL16:
return 1;
case BFD_RELOC_23_PCREL_S2:
*************** alpha_fix_adjustable (f)
*** 1497,1502 ****
--- 1549,1568 ----
case BFD_RELOC_ALPHA_HINT:
return 1;
+ case BFD_RELOC_ALPHA_TLSGD:
+ case BFD_RELOC_ALPHA_TLSLDM:
+ case BFD_RELOC_ALPHA_GOTDTPREL16:
+ case BFD_RELOC_ALPHA_DTPREL_HI16:
+ case BFD_RELOC_ALPHA_DTPREL_LO16:
+ case BFD_RELOC_ALPHA_DTPREL16:
+ case BFD_RELOC_ALPHA_GOTTPREL16:
+ case BFD_RELOC_ALPHA_TPREL_HI16:
+ case BFD_RELOC_ALPHA_TPREL_LO16:
+ case BFD_RELOC_ALPHA_TPREL16:
+ /* ??? No idea why we can't return a reference to .tbss+10, but
+ we're preventing this in the other assemblers. Follow for now. */
+ return 0;
+
default:
return 1;
}
*************** alpha_adjust_symtab_relocs (abfd, sec, p
*** 1666,1672 ****
fixS *fixp;
fixS *next;
fixS *slave;
- unsigned long n_slaves = 0;
/* If seginfo is NULL, we did not create this section; don't do
anything with it. By using a pointer to a pointer, we can update
--- 1732,1737 ----
*************** alpha_adjust_symtab_relocs (abfd, sec, p
*** 1689,1709 ****
switch (fixp->fx_r_type)
{
case BFD_RELOC_ALPHA_LITUSE:
- n_slaves++;
if (fixp->tc_fix_data.info->n_master == 0)
as_bad_where (fixp->fx_file, fixp->fx_line,
_("No !literal!%ld was found"),
fixp->tc_fix_data.info->sequence);
break;
case BFD_RELOC_ALPHA_GPDISP_LO16:
- n_slaves++;
if (fixp->tc_fix_data.info->n_master == 0)
as_bad_where (fixp->fx_file, fixp->fx_line,
_("No ldah !gpdisp!%ld was found"),
fixp->tc_fix_data.info->sequence);
break;
default:
*prevP = fixp;
prevP = &fixp->fx_next;
--- 1754,1792 ----
switch (fixp->fx_r_type)
{
case BFD_RELOC_ALPHA_LITUSE:
if (fixp->tc_fix_data.info->n_master == 0)
as_bad_where (fixp->fx_file, fixp->fx_line,
_("No !literal!%ld was found"),
fixp->tc_fix_data.info->sequence);
+ if (fixp->fx_offset == LITUSE_TLSGD)
+ {
+ if (! fixp->tc_fix_data.info->saw_tlsgd)
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("No !tlsgd!%ld was found"),
+ fixp->tc_fix_data.info->sequence);
+ }
+ else if (fixp->fx_offset == LITUSE_TLSLDM)
+ {
+ if (! fixp->tc_fix_data.info->saw_tlsldm)
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("No !tlsldm!%ld was found"),
+ fixp->tc_fix_data.info->sequence);
+ }
break;
case BFD_RELOC_ALPHA_GPDISP_LO16:
if (fixp->tc_fix_data.info->n_master == 0)
as_bad_where (fixp->fx_file, fixp->fx_line,
_("No ldah !gpdisp!%ld was found"),
fixp->tc_fix_data.info->sequence);
break;
+ case BFD_RELOC_ALPHA_ELF_LITERAL:
+ if (fixp->tc_fix_data.info->saw_tlsgd
+ || fixp->tc_fix_data.info->saw_tlsldm)
+ break;
+ /* FALLTHRU */
+
default:
*prevP = fixp;
prevP = &fixp->fx_next;
*************** alpha_adjust_symtab_relocs (abfd, sec, p
*** 1711,1720 ****
}
}
! /* If there were any dependent relocations, go and add them back to
! the chain. They are linked through the next_reloc field in
! reverse order, so as we go through the next_reloc chain, we
! effectively reverse the chain once again.
Except if there is more than one !literal for a given sequence
number. In that case, the programmer and/or compiler is not sure
--- 1794,1803 ----
}
}
! /* Go back and re-chain dependent relocations. They are currently
! linked through the next_reloc field in reverse order, so as we
! go through the next_reloc chain, we effectively reverse the chain
! once again.
Except if there is more than one !literal for a given sequence
number. In that case, the programmer and/or compiler is not sure
*************** alpha_adjust_symtab_relocs (abfd, sec, p
*** 1734,1739 ****
--- 1817,1843 ----
next = fixp->fx_next;
switch (fixp->fx_r_type)
{
+ case BFD_RELOC_ALPHA_TLSGD:
+ case BFD_RELOC_ALPHA_TLSLDM:
+ if (!fixp->tc_fix_data.info)
+ break;
+ if (fixp->tc_fix_data.info->n_master == 0)
+ break;
+ else if (fixp->tc_fix_data.info->n_master > 1)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("too many !literal!%ld for %s"),
+ fixp->tc_fix_data.info->sequence,
+ (fixp->fx_r_type == BFD_RELOC_ALPHA_TLSGD
+ ? "!tlsgd" : "!tlsldm"));
+ break;
+ }
+
+ fixp->tc_fix_data.info->master->fx_next = fixp->fx_next;
+ fixp->fx_next = fixp->tc_fix_data.info->master;
+ fixp = fixp->fx_next;
+ /* FALLTHRU */
+
case BFD_RELOC_ALPHA_ELF_LITERAL:
if (fixp->tc_fix_data.info->n_master == 1
&& ! fixp->tc_fix_data.info->multi_section_p)
*************** debug_exp (tok, ntok)
*** 1820,1834 ****
case O_lituse_base: name = "O_lituse_base"; break;
case O_lituse_bytoff: name = "O_lituse_bytoff"; break;
case O_lituse_jsr: name = "O_lituse_jsr"; break;
case O_gpdisp: name = "O_gpdisp"; break;
case O_gprelhigh: name = "O_gprelhigh"; break;
case O_gprellow: name = "O_gprellow"; break;
case O_gprel: name = "O_gprel"; break;
case O_samegp: name = "O_samegp"; break;
! case O_md13: name = "O_md13"; break;
! case O_md14: name = "O_md14"; break;
! case O_md15: name = "O_md15"; break;
! case O_md16: name = "O_md16"; break;
}
fprintf (stderr, ", %s(%s, %s, %d)", name,
--- 1924,1946 ----
case O_lituse_base: name = "O_lituse_base"; break;
case O_lituse_bytoff: name = "O_lituse_bytoff"; break;
case O_lituse_jsr: name = "O_lituse_jsr"; break;
+ case O_lituse_tlsgd: name = "O_lituse_tlsgd"; break;
+ case O_lituse_tlsldm: name = "O_lituse_tlsldm"; break;
case O_gpdisp: name = "O_gpdisp"; break;
case O_gprelhigh: name = "O_gprelhigh"; break;
case O_gprellow: name = "O_gprellow"; break;
case O_gprel: name = "O_gprel"; break;
case O_samegp: name = "O_samegp"; break;
! case O_tlsgd: name = "O_tlsgd"; break;
! case O_tlsldm: name = "O_tlsldm"; break;
! case O_gotdtprel: name = "O_gotdtprel"; break;
! case O_dtprelhi: name = "O_dtprelhi"; break;
! case O_dtprello: name = "O_dtprello"; break;
! case O_dtprel: name = "O_dtprel"; break;
! case O_gottprel: name = "O_gottprel"; break;
! case O_tprelhi: name = "O_tprelhi"; break;
! case O_tprello: name = "O_tprello"; break;
! case O_tprel: name = "O_tprel"; break;
}
fprintf (stderr, ", %s(%s, %s, %d)", name,
*************** emit_insn (insn)
*** 2479,2485 ****
{
const struct alpha_operand *operand = (const struct alpha_operand *) 0;
struct alpha_fixup *fixup = &insn->fixups[i];
! struct alpha_reloc_tag *info;
int size, pcrel;
fixS *fixP;
--- 2591,2597 ----
{
const struct alpha_operand *operand = (const struct alpha_operand *) 0;
struct alpha_fixup *fixup = &insn->fixups[i];
! struct alpha_reloc_tag *info = NULL;
int size, pcrel;
fixS *fixP;
*************** emit_insn (insn)
*** 2521,2526 ****
--- 2633,2646 ----
case BFD_RELOC_GPREL16:
case BFD_RELOC_ALPHA_GPREL_HI16:
case BFD_RELOC_ALPHA_GPREL_LO16:
+ case BFD_RELOC_ALPHA_GOTDTPREL16:
+ case BFD_RELOC_ALPHA_DTPREL_HI16:
+ case BFD_RELOC_ALPHA_DTPREL_LO16:
+ case BFD_RELOC_ALPHA_DTPREL16:
+ case BFD_RELOC_ALPHA_GOTTPREL16:
+ case BFD_RELOC_ALPHA_TPREL_HI16:
+ case BFD_RELOC_ALPHA_TPREL_LO16:
+ case BFD_RELOC_ALPHA_TPREL16:
fixP->fx_no_overflow = 1;
break;
*************** emit_insn (insn)
*** 2555,2561 ****
--- 2675,2684 ----
case BFD_RELOC_ALPHA_ELF_LITERAL:
fixP->fx_no_overflow = 1;
+ if (insn->sequence == 0)
+ break;
info = get_alpha_reloc_tag (insn->sequence);
+ info->master = fixP;
info->n_master++;
if (info->segment != now_seg)
info->multi_section_p = 1;
*************** emit_insn (insn)
*** 2573,2584 ****
goto do_lituse;
case DUMMY_RELOC_LITUSE_JSR:
fixP->fx_offset = LITUSE_JSR;
do_lituse:
fixP->fx_addsy = section_symbol (now_seg);
fixP->fx_r_type = BFD_RELOC_ALPHA_LITUSE;
info = get_alpha_reloc_tag (insn->sequence);
! info->n_slaves++;
fixP->tc_fix_data.info = info;
fixP->tc_fix_data.next_reloc = info->slaves;
info->slaves = fixP;
--- 2696,2726 ----
goto do_lituse;
case DUMMY_RELOC_LITUSE_JSR:
fixP->fx_offset = LITUSE_JSR;
+ goto do_lituse;
+ case DUMMY_RELOC_LITUSE_TLSGD:
+ fixP->fx_offset = LITUSE_TLSGD;
+ goto do_lituse;
+ case DUMMY_RELOC_LITUSE_TLSLDM:
+ fixP->fx_offset = LITUSE_TLSLDM;
+ goto do_lituse;
do_lituse:
fixP->fx_addsy = section_symbol (now_seg);
fixP->fx_r_type = BFD_RELOC_ALPHA_LITUSE;
info = get_alpha_reloc_tag (insn->sequence);
! if (fixup->reloc == DUMMY_RELOC_LITUSE_TLSGD)
! info->saw_lu_tlsgd = 1;
! else if (fixup->reloc == DUMMY_RELOC_LITUSE_TLSLDM)
! info->saw_lu_tlsldm = 1;
! if (++info->n_slaves > 1)
! {
! if (info->saw_lu_tlsgd)
! as_bad (_("too many lituse insns for !lituse_tlsgd!%ld"),
! insn->sequence);
! else if (info->saw_lu_tlsldm)
! as_bad (_("too many lituse insns for !lituse_tlsldm!%ld"),
! insn->sequence);
! }
fixP->tc_fix_data.info = info;
fixP->tc_fix_data.next_reloc = info->slaves;
info->slaves = fixP;
*************** emit_insn (insn)
*** 2586,2591 ****
--- 2728,2765 ----
info->multi_section_p = 1;
break;
+ case BFD_RELOC_ALPHA_TLSGD:
+ fixP->fx_no_overflow = 1;
+
+ if (insn->sequence == 0)
+ break;
+ info = get_alpha_reloc_tag (insn->sequence);
+ if (info->saw_tlsgd)
+ as_bad (_("duplicate !tlsgd!%ld"), insn->sequence);
+ else if (info->saw_tlsldm)
+ as_bad (_("sequence number in use for !tlsldm!%ld"),
+ insn->sequence);
+ else
+ info->saw_tlsgd = 1;
+ fixP->tc_fix_data.info = info;
+ break;
+
+ case BFD_RELOC_ALPHA_TLSLDM:
+ fixP->fx_no_overflow = 1;
+
+ if (insn->sequence == 0)
+ break;
+ info = get_alpha_reloc_tag (insn->sequence);
+ if (info->saw_tlsldm)
+ as_bad (_("duplicate !tlsldm!%ld"), insn->sequence);
+ else if (info->saw_tlsgd)
+ as_bad (_("sequence number in use for !tlsgd!%ld"),
+ insn->sequence);
+ else
+ info->saw_tlsldm = 1;
+ fixP->tc_fix_data.info = info;
+ break;
+
default:
if ((int) fixup->reloc < 0)
{
*************** static const char * const extXh_op[] = {
*** 2715,2721 ****
static const char * const mskXl_op[] = { "mskbl", "mskwl", "mskll", "mskql" };
static const char * const mskXh_op[] = { NULL, "mskwh", "msklh", "mskqh" };
static const char * const stX_op[] = { "stb", "stw", "stl", "stq" };
- static const char * const ldX_op[] = { "ldb", "ldw", "ldll", "ldq" };
static const char * const ldXu_op[] = { "ldbu", "ldwu", NULL, NULL };
/* Implement the ldgp macro. */
--- 2889,2894 ----
Index: gas/testsuite/gas/alpha/alpha.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/alpha/alpha.exp,v
retrieving revision 1.3
diff -c -p -d -r1.3 alpha.exp
*** gas/testsuite/gas/alpha/alpha.exp 9 Feb 2002 22:55:06 -0000 1.3
--- gas/testsuite/gas/alpha/alpha.exp 30 May 2002 21:41:27 -0000
*************** if { [istarget alpha*-*-*] } then {
*** 29,34 ****
--- 29,37 ----
run_dump_test "elf-reloc-4"
run_dump_test "elf-reloc-5"
run_list_test "elf-reloc-6" ""
+ run_dump_test "elf-tls-1"
+ run_list_test "elf-tls-2" ""
+ run_list_test "elf-tls-3" ""
}
run_dump_test "fp"
Index: gas/testsuite/gas/alpha/elf-tls-1.d
===================================================================
RCS file: gas/testsuite/gas/alpha/elf-tls-1.d
diff -N gas/testsuite/gas/alpha/elf-tls-1.d
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gas/testsuite/gas/alpha/elf-tls-1.d 30 May 2002 21:41:27 -0000
***************
*** 0 ****
--- 1,29 ----
+ #objdump: -r
+ #name: alpha elf-tls-1
+
+ .*: file format elf64-alpha
+
+ RELOCATION RECORDS FOR \[\.text\]:
+ OFFSET TYPE VALUE
+ 0*0000004 TLSGD a
+ 0*0000000 ELF_LITERAL __tls_get_addr
+ 0*0000008 LITUSE \.text\+0x0*0000004
+ 0*0000008 HINT __tls_get_addr
+ 0*000000c HINT __tls_get_addr
+ 0*0000014 TLSLDM b
+ 0*0000010 ELF_LITERAL __tls_get_addr
+ 0*000000c LITUSE \.text\+0x0*0000005
+ 0*0000018 TLSGD c
+ 0*000001c TLSLDM d
+ 0*0000020 TLSGD e
+ 0*0000024 TLSLDM f
+ 0*0000028 GOTDTPREL g
+ 0*000002c DTPRELHI h
+ 0*0000030 DTPRELLO i
+ 0*0000034 DTPREL16 j
+ 0*0000038 GOTTPREL k
+ 0*000003c TPRELHI l
+ 0*0000040 TPRELLO m
+ 0*0000044 TPREL16 n
+
+
Index: gas/testsuite/gas/alpha/elf-tls-1.s
===================================================================
RCS file: gas/testsuite/gas/alpha/elf-tls-1.s
diff -N gas/testsuite/gas/alpha/elf-tls-1.s
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gas/testsuite/gas/alpha/elf-tls-1.s 30 May 2002 21:41:27 -0000
***************
*** 0 ****
--- 1,24 ----
+ .set nomacro
+ ldq $27, __tls_get_addr($29) !literal!1
+ ldq $16, a($29) !tlsgd!1
+ jsr $26, ($27), __tls_get_addr !lituse_tlsgd!1
+
+ jsr $26, ($27), __tls_get_addr !lituse_tlsldm!2
+ ldq $27, __tls_get_addr($29) !literal!2
+ ldq $16, b($29) !tlsldm!2
+
+ ldq $16, c($29) !tlsgd
+ ldq $16, d($29) !tlsldm
+
+ ldq $16, e($29) !tlsgd!3
+ ldq $16, f($29) !tlsldm!4
+
+ ldq $16, g($29) !gotdtprel
+ ldah $16, h($31) !dtprelhi
+ lda $16, i($16) !dtprello
+ lda $16, j($31) !dtprel
+
+ ldq $16, k($29) !gottprel
+ ldah $16, l($31) !tprelhi
+ lda $16, m($16) !tprello
+ lda $16, n($31) !tprel
Index: gas/testsuite/gas/alpha/elf-tls-2.l
===================================================================
RCS file: gas/testsuite/gas/alpha/elf-tls-2.l
diff -N gas/testsuite/gas/alpha/elf-tls-2.l
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gas/testsuite/gas/alpha/elf-tls-2.l 30 May 2002 21:41:27 -0000
***************
*** 0 ****
--- 1,9 ----
+ .*: Assembler messages:
+ .*:5: Error: too many lituse insns for !lituse_tlsgd!1
+ .*:10: Error: too many lituse insns for !lituse_tlsldm!2
+ .*:15: Error: too many lituse insns for !lituse_tlsgd!3
+ .*:20: Error: too many lituse insns for !lituse_tlsldm!4
+ .*:23: Error: duplicate !tlsgd!5
+ .*:26: Error: duplicate !tlsldm!6
+ .*:29: Error: sequence number in use for !tlsgd!7
+ .*:32: Error: sequence number in use for !tlsldm!8
Index: gas/testsuite/gas/alpha/elf-tls-2.s
===================================================================
RCS file: gas/testsuite/gas/alpha/elf-tls-2.s
diff -N gas/testsuite/gas/alpha/elf-tls-2.s
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gas/testsuite/gas/alpha/elf-tls-2.s 30 May 2002 21:41:27 -0000
***************
*** 0 ****
--- 1,32 ----
+ .set nomacro
+ ldq $16, c($29) !tlsgd!1
+ ldq $27, __tls_get_addr($29) !literal!1
+ jsr $26, ($27), __tls_get_addr !lituse_tlsgd!1
+ jsr $26, ($27), __tls_get_addr !lituse_jsr!1
+
+ ldq $16, d($29) !tlsldm!2
+ ldq $27, __tls_get_addr($29) !literal!2
+ jsr $26, ($27), __tls_get_addr !lituse_jsr!2
+ jsr $26, ($27), __tls_get_addr !lituse_tlsldm!2
+
+ ldq $16, g($29) !tlsgd!3
+ ldq $27, __tls_get_addr($29) !literal!3
+ jsr $26, ($27), __tls_get_addr !lituse_tlsgd!3
+ jsr $26, ($27), __tls_get_addr !lituse_tlsgd!3
+
+ ldq $16, h($29) !tlsldm!4
+ ldq $27, __tls_get_addr($29) !literal!4
+ jsr $26, ($27), __tls_get_addr !lituse_tlsldm!4
+ jsr $26, ($27), __tls_get_addr !lituse_tlsldm!4
+
+ ldq $16, i($29) !tlsgd!5
+ ldq $16, i($29) !tlsgd!5
+
+ ldq $16, j($29) !tlsldm!6
+ ldq $16, j($29) !tlsldm!6
+
+ ldq $16, k($29) !tlsgd!7
+ ldq $16, k($29) !tlsldm!7
+
+ ldq $16, l($29) !tlsldm!8
+ ldq $16, l($29) !tlsgd!8
Index: gas/testsuite/gas/alpha/elf-tls-3.l
===================================================================
RCS file: gas/testsuite/gas/alpha/elf-tls-3.l
diff -N gas/testsuite/gas/alpha/elf-tls-3.l
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gas/testsuite/gas/alpha/elf-tls-3.l 30 May 2002 21:41:27 -0000
***************
*** 0 ****
--- 1,7 ----
+ .*: Assembler messages:
+ .*:3: Error: No !tlsgd!1 was found
+ .*:6: Error: No !tlsldm!2 was found
+ .*:18: Error: No !tlsldm!5 was found
+ .*:22: Error: No !tlsgd!6 was found
+ .*:8: Error: too many !literal!3 for !tlsgd
+ .*:12: Error: too many !literal!4 for !tlsldm
Index: gas/testsuite/gas/alpha/elf-tls-3.s
===================================================================
RCS file: gas/testsuite/gas/alpha/elf-tls-3.s
diff -N gas/testsuite/gas/alpha/elf-tls-3.s
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gas/testsuite/gas/alpha/elf-tls-3.s 30 May 2002 21:41:27 -0000
***************
*** 0 ****
--- 1,22 ----
+ .set nomacro
+ ldq $27, __tls_get_addr($29) !literal!1
+ jsr $26, ($27), __tls_get_addr !lituse_tlsgd!1
+
+ ldq $27, __tls_get_addr($29) !literal!2
+ jsr $26, ($27), __tls_get_addr !lituse_tlsldm!2
+
+ ldq $16, a($29) !tlsgd!3
+ ldq $27, __tls_get_addr($29) !literal!3
+ ldq $27, __tls_get_addr($29) !literal!3
+
+ ldq $16, b($29) !tlsldm!4
+ ldq $27, __tls_get_addr($29) !literal!4
+ ldq $27, __tls_get_addr($29) !literal!4
+
+ ldq $16, e($29) !tlsgd!5
+ ldq $27, __tls_get_addr($29) !literal!5
+ jsr $26, ($27), __tls_get_addr !lituse_tlsldm!5
+
+ ldq $16, f($29) !tlsldm!6
+ ldq $27, __tls_get_addr($29) !literal!6
+ jsr $26, ($27), __tls_get_addr !lituse_tlsgd!6
Index: include/elf/alpha.h
===================================================================
RCS file: /cvs/src/src/include/elf/alpha.h,v
retrieving revision 1.6
diff -c -p -d -r1.6 alpha.h
*** include/elf/alpha.h 9 Feb 2002 22:54:16 -0000 1.6
--- include/elf/alpha.h 30 May 2002 21:41:27 -0000
*************** START_RELOC_NUMBERS (elf_alpha_reloc_typ
*** 99,104 ****
--- 99,119 ----
STO_ALPHA_STD_GPLOAD. */
RELOC_NUMBER (R_ALPHA_BRSGP, 28)
+ /* Thread-Local Storage. */
+ RELOC_NUMBER (R_ALPHA_TLSGD, 29)
+ RELOC_NUMBER (R_ALPHA_TLSLDM, 30)
+ RELOC_NUMBER (R_ALPHA_DTPMOD64, 31)
+ RELOC_NUMBER (R_ALPHA_GOTDTPREL, 32)
+ RELOC_NUMBER (R_ALPHA_DTPREL64, 33)
+ RELOC_NUMBER (R_ALPHA_DTPRELHI, 34)
+ RELOC_NUMBER (R_ALPHA_DTPRELLO, 35)
+ RELOC_NUMBER (R_ALPHA_DTPREL16, 36)
+ RELOC_NUMBER (R_ALPHA_GOTTPREL, 37)
+ RELOC_NUMBER (R_ALPHA_TPREL64, 38)
+ RELOC_NUMBER (R_ALPHA_TPRELHI, 39)
+ RELOC_NUMBER (R_ALPHA_TPRELLO, 40)
+ RELOC_NUMBER (R_ALPHA_TPREL16, 41)
+
END_RELOC_NUMBERS (R_ALPHA_max)
#endif /* _ELF_ALPHA_H */