mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 18:14:13 +08:00
* elf.c (_bfd_elf_make_section_from_shdr): Set SEC_THREAD_LOCAL
for symbols from SHF_TLS section. (_bfd_elf_print_private_bfd_data): Add PT_TLS. (elf_fake_sections): Set SHF_TLS for SEC_THREAD_LOCAL sections. (map_sections_to_segments): Build PT_TLS segment if necessary. (assign_file_positions_for_segments): Likewise. (get_program_header_size): Account for PT_TLS segment. (swap_out_syms): Set type of BSF_THREAD_LOCAL symbols and symbols from SEC_THREAD_LOCAL sections to STT_TLS. * reloc.c: Add 386 and IA-64 TLS relocs. * section.c (SEC_THREAD_LOCAL): Define. (SEC_CONSTRUCTOR_TEXT, SEC_CONSTRUCTOR_DATA, SEC_CONSTRUCTOR_BSS): Remove. * elflink.h (elf_link_add_object_symbols): Support .tcommon. (size_dynamic_sections): If DF_STATIC_TLS, set DF_FLAGS unconditionally. (struct elf_final_link_info): Add first_tls_sec. (elf_bfd_final_link): Set first_tls_sec. Compute elf_hash_table (info)->tls_segment. (elf_link_output_extsym): Handle STT_TLS symbols. (elf_link_input_bfd): Likewise. * syms.c (BSF_THREAD_LOCAL): Define. * bfd-in2.h: Rebuilt. * libbfd.h: Rebuilt. * elf32-i386.c (elf_i386_tls_transition, dtpoff_base, tpoff, elf_i386_mkobject, elf_i386_object_p): New functions. (elf_howto_table): Add TLS relocs. (elf_i386_reloc_type_lookup): Support TLS relocs. (elf_i386_info_to_howto_rel): Likewise. (struct elf_i386_link_hash_entry): Add tls_type. (struct elf_i386_obj_tdata): New. (elf_i386_hash_entry, elf_i386_tdata, elf_i386_local_got_tls_type): New macros. (struct elf_i386_link_hash_table): Add tls_ldm_got. (link_hash_newfunc): Clear tls_type. (elf_i386_check_relocs): Support TLS relocs. (elf_i386_gc_sweep_hook): Likewise. (allocate_dynrelocs): Likewise. (elf_i386_size_dynamic_sections): Likewise. (elf_i386_relocate_section): Likewise. (elf_i386_finish_dynamic_symbol): Likewise. (bfd_elf32_mkobject, elf_backend_object_p): Define. * elfxx-ia64.c (struct elfNN_ia64_dyn_sym_info): Add tprel_offset, dtpmod_offset, dtprel_offset, tprel_done, dtpmod_done, dtprel_done, want_tprel, want_dtpmod, want_dtprel. (elfNN_ia64_tprel_base, elfNN_ia64_dtprel_base): New functions. (ia64_howto_table): Add TLS relocs, rename R_IA64_LTOFF_TP22 to R_IA64_LTOFF_TPREL22. (elf_code_to_howto_index): Add TLS relocs. (elfNN_ia64_check_relocs): Support TLS relocs. (allocate_global_data_got): Account for TLS .got data. (allocate_dynrel_entries): Account for TLS dynamic relocations. (elfNN_ia64_install_value): Supprt TLS relocs. (set_got_entry): Support TLS relocs. (elfNN_ia64_relocate_section): Likewise. * config/obj-elf.c (elf_common): Renamed from obj_elf_common. (obj_elf_common): Call elf_common. (obj_elf_tls_common): New function. (elf_pseudo_tab): Support .tls_common. (special_sections): Add .tdata and .tbss. (obj_elf_change_section): Set SEC_THREAD_LOCAL for SHF_TLS sections. (obj_elf_parse_section_letters): Support T in section flags (SHF_TLS). (obj_elf_parse_section_letters): Include T in error message. * config/tc-ppc.c (ppc_section_letter): Likewise. * config/tc-alpha.c (alpha_elf_section_letter): Likewise. (tc_gen_reloc): Handle SEC_THREAD_LOCAL the same way as SEC_MERGE. * config/tc-sparc.c (md_apply_fix3): Likewise. * config/tc-i386.c (tc_i386_fix_adjustable): Add TLS relocs. Define them if not BFD_ASSEMBLER. (lex_got): Support @TLSGD, @TLSLDM, @GOTTPOFF, @TPOFF, @DTPOFF and @NTPOFF. (md_apply_fix3): Add TLS relocs. * config/tc-ia64.c (enum reloc_func): Add FUNC_DTP_MODULE, FUNC_DTP_RELATIVE, FUNC_TP_RELATIVE, FUNC_LT_DTP_MODULE, FUNC_LT_DTP_RELATIVE, FUNC_LT_TP_RELATIVE. (pseudo_func): Support @dtpmod(), @dtprel() and @tprel(). (ia64_elf_section_letter): Include T in error message. (md_begin): Support TLS operators. (md_operand): Likewise. (ia64_gen_real_reloc_type): Support TLS relocs. * testsuite/gas/i386/tlspic.s: New file. * testsuite/gas/i386/tlsd.s: New file. * testsuite/gas/i386/tlsnopic.s: New file. * testsuite/gas/i386/tlsd.d: New file. * testsuite/gas/i386/tlsnopic.d: New file. * testsuite/gas/i386/tlspic.d: New file. * testsuite/gas/i386/i386.exp: Add tlsd, tlsnopic and tlspic tests. * testsuite/gas/ia64/tls.s: New file. * testsuite/gas/ia64/tls.d: New file. * testsuite/gas/ia64/ia64.exp: Add tls test. * write.c (adjust_reloc_syms): Don't change symbols in SEC_THREAD_LOCAL sections to STT_SECTION + addend. * elf/common.h (PT_TLS, SHF_TLS, STT_TLS, DF_STATIC_TLS): Define. * elf/ia64.h (R_IA64_LTOFF_TPREL22): Renamed from R_IA64_LTOFF_TP22. * elf/i386.h: Add TLS relocs. * scripttempl/elf.sc: Add .rel{,a}.t{bss,data}, .tdata and .tbss. * ldlang.c (lang_add_section): Set SEC_THREAD_LOCAL for output section if necessary. Handle .tbss. (lang_size_sections): Clear _raw_size for .tbss section (it allocates space in PT_TLS segment only). * ldwrite.c (build_link_order): Build link order for .tbss too. * readelf.c (get_segment_type): Add PT_TLS. (get_elf_section_flags): Add SHF_TLS. (get_dynamic_flags): Optimize. Add DF_STATIC_TLS. (process_dynamic_segment): Use puts instead of printf. (get_symbol_type): Support STT_TLS. * objdump.c (dump_section_header): Remove SEC_CONSTRUCTOR_TEXT, SEC_CONSTRUCTOR_DATA, SEC_CONSTRUCTOR_BSS. Add SEC_THREAD_LOCAL.
This commit is contained in:
parent
baf0cc5e96
commit
13ae64f3c7
@ -1,3 +1,61 @@
|
||||
2002-05-23 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* elf.c (_bfd_elf_make_section_from_shdr): Set SEC_THREAD_LOCAL
|
||||
for symbols from SHF_TLS section.
|
||||
(_bfd_elf_print_private_bfd_data): Add PT_TLS.
|
||||
(elf_fake_sections): Set SHF_TLS for SEC_THREAD_LOCAL sections.
|
||||
(map_sections_to_segments): Build PT_TLS segment if necessary.
|
||||
(assign_file_positions_for_segments): Likewise.
|
||||
(get_program_header_size): Account for PT_TLS segment.
|
||||
(swap_out_syms): Set type of BSF_THREAD_LOCAL symbols and symbols from
|
||||
SEC_THREAD_LOCAL sections to STT_TLS.
|
||||
* reloc.c: Add 386 and IA-64 TLS relocs.
|
||||
* section.c (SEC_THREAD_LOCAL): Define.
|
||||
(SEC_CONSTRUCTOR_TEXT, SEC_CONSTRUCTOR_DATA, SEC_CONSTRUCTOR_BSS):
|
||||
Remove.
|
||||
* elflink.h (elf_link_add_object_symbols): Support .tcommon.
|
||||
(size_dynamic_sections): If DF_STATIC_TLS, set DF_FLAGS
|
||||
unconditionally.
|
||||
(struct elf_final_link_info): Add first_tls_sec.
|
||||
(elf_bfd_final_link): Set first_tls_sec.
|
||||
Compute elf_hash_table (info)->tls_segment.
|
||||
(elf_link_output_extsym): Handle STT_TLS symbols.
|
||||
(elf_link_input_bfd): Likewise.
|
||||
* syms.c (BSF_THREAD_LOCAL): Define.
|
||||
* bfd-in2.h: Rebuilt.
|
||||
* libbfd.h: Rebuilt.
|
||||
* elf32-i386.c (elf_i386_tls_transition, dtpoff_base, tpoff,
|
||||
elf_i386_mkobject, elf_i386_object_p): New functions.
|
||||
(elf_howto_table): Add TLS relocs.
|
||||
(elf_i386_reloc_type_lookup): Support TLS relocs.
|
||||
(elf_i386_info_to_howto_rel): Likewise.
|
||||
(struct elf_i386_link_hash_entry): Add tls_type.
|
||||
(struct elf_i386_obj_tdata): New.
|
||||
(elf_i386_hash_entry, elf_i386_tdata, elf_i386_local_got_tls_type):
|
||||
New macros.
|
||||
(struct elf_i386_link_hash_table): Add tls_ldm_got.
|
||||
(link_hash_newfunc): Clear tls_type.
|
||||
(elf_i386_check_relocs): Support TLS relocs.
|
||||
(elf_i386_gc_sweep_hook): Likewise.
|
||||
(allocate_dynrelocs): Likewise.
|
||||
(elf_i386_size_dynamic_sections): Likewise.
|
||||
(elf_i386_relocate_section): Likewise.
|
||||
(elf_i386_finish_dynamic_symbol): Likewise.
|
||||
(bfd_elf32_mkobject, elf_backend_object_p): Define.
|
||||
* elfxx-ia64.c (struct elfNN_ia64_dyn_sym_info): Add tprel_offset,
|
||||
dtpmod_offset, dtprel_offset, tprel_done, dtpmod_done, dtprel_done,
|
||||
want_tprel, want_dtpmod, want_dtprel.
|
||||
(elfNN_ia64_tprel_base, elfNN_ia64_dtprel_base): New functions.
|
||||
(ia64_howto_table): Add TLS relocs, rename R_IA64_LTOFF_TP22 to
|
||||
R_IA64_LTOFF_TPREL22.
|
||||
(elf_code_to_howto_index): Add TLS relocs.
|
||||
(elfNN_ia64_check_relocs): Support TLS relocs.
|
||||
(allocate_global_data_got): Account for TLS .got data.
|
||||
(allocate_dynrel_entries): Account for TLS dynamic relocations.
|
||||
(elfNN_ia64_install_value): Supprt TLS relocs.
|
||||
(set_got_entry): Support TLS relocs.
|
||||
(elfNN_ia64_relocate_section): Likewise.
|
||||
|
||||
2002-05-23 Nick Clifton <nickc@cambridge.redhat.com>
|
||||
|
||||
* elf32-arm.h (elf32_arm_final_link_relocate): For the Thumb
|
||||
|
@ -1068,12 +1068,6 @@ typedef struct sec
|
||||
standard data. */
|
||||
#define SEC_CONSTRUCTOR 0x100
|
||||
|
||||
/* The section is a constructor, and should be placed at the
|
||||
end of the text, data, or bss section(?). */
|
||||
#define SEC_CONSTRUCTOR_TEXT 0x1100
|
||||
#define SEC_CONSTRUCTOR_DATA 0x2100
|
||||
#define SEC_CONSTRUCTOR_BSS 0x3100
|
||||
|
||||
/* The section has contents - a data section could be
|
||||
<<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>; a debug section could be
|
||||
<<SEC_HAS_CONTENTS>> */
|
||||
@ -1094,6 +1088,9 @@ typedef struct sec
|
||||
sections. */
|
||||
#define SEC_COFF_SHARED_LIBRARY 0x800
|
||||
|
||||
/* The section contains thread local data. */
|
||||
#define SEC_THREAD_LOCAL 0x1000
|
||||
|
||||
/* The section has GOT references. This flag is only for the
|
||||
linker, and is currently only used by the elf32-hppa back end.
|
||||
It will be set if global offset table references were detected
|
||||
@ -2211,6 +2208,15 @@ to compensate for the borrow when the low bits are added. */
|
||||
BFD_RELOC_386_RELATIVE,
|
||||
BFD_RELOC_386_GOTOFF,
|
||||
BFD_RELOC_386_GOTPC,
|
||||
BFD_RELOC_386_TLS_LE,
|
||||
BFD_RELOC_386_TLS_GD,
|
||||
BFD_RELOC_386_TLS_LDM,
|
||||
BFD_RELOC_386_TLS_LDO_32,
|
||||
BFD_RELOC_386_TLS_IE_32,
|
||||
BFD_RELOC_386_TLS_LE_32,
|
||||
BFD_RELOC_386_TLS_DTPMOD32,
|
||||
BFD_RELOC_386_TLS_DTPOFF32,
|
||||
BFD_RELOC_386_TLS_TPOFF32,
|
||||
|
||||
/* x86-64/elf relocations */
|
||||
BFD_RELOC_X86_64_GOT32,
|
||||
@ -2922,12 +2928,25 @@ this offset in the reloc's section offset. */
|
||||
BFD_RELOC_IA64_IPLTMSB,
|
||||
BFD_RELOC_IA64_IPLTLSB,
|
||||
BFD_RELOC_IA64_COPY,
|
||||
BFD_RELOC_IA64_TPREL22,
|
||||
BFD_RELOC_IA64_TPREL64MSB,
|
||||
BFD_RELOC_IA64_TPREL64LSB,
|
||||
BFD_RELOC_IA64_LTOFF_TP22,
|
||||
BFD_RELOC_IA64_LTOFF22X,
|
||||
BFD_RELOC_IA64_LDXMOV,
|
||||
BFD_RELOC_IA64_TPREL14,
|
||||
BFD_RELOC_IA64_TPREL22,
|
||||
BFD_RELOC_IA64_TPREL64I,
|
||||
BFD_RELOC_IA64_TPREL64MSB,
|
||||
BFD_RELOC_IA64_TPREL64LSB,
|
||||
BFD_RELOC_IA64_LTOFF_TPREL22,
|
||||
BFD_RELOC_IA64_DTPMOD64MSB,
|
||||
BFD_RELOC_IA64_DTPMOD64LSB,
|
||||
BFD_RELOC_IA64_LTOFF_DTPMOD22,
|
||||
BFD_RELOC_IA64_DTPREL14,
|
||||
BFD_RELOC_IA64_DTPREL22,
|
||||
BFD_RELOC_IA64_DTPREL64I,
|
||||
BFD_RELOC_IA64_DTPREL32MSB,
|
||||
BFD_RELOC_IA64_DTPREL32LSB,
|
||||
BFD_RELOC_IA64_DTPREL64MSB,
|
||||
BFD_RELOC_IA64_DTPREL64LSB,
|
||||
BFD_RELOC_IA64_LTOFF_DTPREL22,
|
||||
|
||||
/* Motorola 68HC11 reloc.
|
||||
This is the 8 bits high part of an absolute address. */
|
||||
@ -3138,6 +3157,9 @@ typedef struct symbol_cache_entry
|
||||
as well. */
|
||||
#define BSF_DEBUGGING_RELOC 0x20000
|
||||
|
||||
/* This symbol is thread local. Used in ELF. */
|
||||
#define BSF_THREAD_LOCAL 0x40000
|
||||
|
||||
flagword flags;
|
||||
|
||||
/* A pointer to the section to which this symbol is
|
||||
|
@ -234,6 +234,14 @@ enum elf_link_info_type
|
||||
ELF_INFO_TYPE_LAST
|
||||
};
|
||||
|
||||
/* Cached start, size and alignment of PT_TLS segment. */
|
||||
struct elf_link_tls_segment
|
||||
{
|
||||
bfd_vma start;
|
||||
bfd_size_type size;
|
||||
unsigned int align;
|
||||
};
|
||||
|
||||
/* ELF linker hash table. */
|
||||
|
||||
struct elf_link_hash_table
|
||||
@ -286,6 +294,9 @@ struct elf_link_hash_table
|
||||
/* A linked list of DT_RPATH/DT_RUNPATH names found in dynamic
|
||||
objects included in the link. */
|
||||
struct bfd_link_needed_list *runpath;
|
||||
|
||||
/* Cached start, size and alignment of PT_TLS segment. */
|
||||
struct elf_link_tls_segment *tls_segment;
|
||||
};
|
||||
|
||||
/* Look up an entry in an ELF linker hash table. */
|
||||
|
71
bfd/elf.c
71
bfd/elf.c
@ -591,6 +591,8 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
|
||||
if (hdr->sh_flags & SHF_GROUP)
|
||||
if (!setup_group (abfd, hdr, newsect))
|
||||
return false;
|
||||
if ((hdr->sh_flags & SHF_TLS) != 0)
|
||||
flags |= SEC_THREAD_LOCAL;
|
||||
|
||||
/* The debugging sections appear to be recognized only by name, not
|
||||
any sort of flag. */
|
||||
@ -883,6 +885,7 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
|
||||
case PT_NOTE: pt = "NOTE"; break;
|
||||
case PT_SHLIB: pt = "SHLIB"; break;
|
||||
case PT_PHDR: pt = "PHDR"; break;
|
||||
case PT_TLS: pt = "TLS"; break;
|
||||
case PT_GNU_EH_FRAME: pt = "EH_FRAME"; break;
|
||||
default: sprintf (buf, "0x%lx", p->p_type); pt = buf; break;
|
||||
}
|
||||
@ -2274,6 +2277,8 @@ elf_fake_sections (abfd, asect, failedptrarg)
|
||||
}
|
||||
if (elf_group_name (asect) != NULL)
|
||||
this_hdr->sh_flags |= SHF_GROUP;
|
||||
if ((asect->flags & SEC_THREAD_LOCAL) != 0)
|
||||
this_hdr->sh_flags |= SHF_TLS;
|
||||
|
||||
/* Check for processor-specific section types. */
|
||||
if (bed->elf_backend_fake_sections
|
||||
@ -2956,6 +2961,8 @@ map_sections_to_segments (abfd)
|
||||
asection **hdrpp;
|
||||
boolean phdr_in_segment = true;
|
||||
boolean writable;
|
||||
int tls_count = 0;
|
||||
asection *first_tls = NULL;
|
||||
asection *dynsec, *eh_frame_hdr;
|
||||
bfd_size_type amt;
|
||||
|
||||
@ -3194,6 +3201,39 @@ map_sections_to_segments (abfd)
|
||||
*pm = m;
|
||||
pm = &m->next;
|
||||
}
|
||||
if (s->flags & SEC_THREAD_LOCAL)
|
||||
{
|
||||
if (! tls_count)
|
||||
first_tls = s;
|
||||
tls_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* If there are any SHF_TLS output sections, add PT_TLS segment. */
|
||||
if (tls_count > 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
amt = sizeof (struct elf_segment_map);
|
||||
amt += (tls_count - 1) * sizeof (asection *);
|
||||
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
|
||||
if (m == NULL)
|
||||
goto error_return;
|
||||
m->next = NULL;
|
||||
m->p_type = PT_TLS;
|
||||
m->count = tls_count;
|
||||
/* Mandated PF_R. */
|
||||
m->p_flags = PF_R;
|
||||
m->p_flags_valid = 1;
|
||||
for (i = 0; i < tls_count; ++i)
|
||||
{
|
||||
BFD_ASSERT (first_tls->flags & SEC_THREAD_LOCAL);
|
||||
m->sections[i] = first_tls;
|
||||
first_tls = first_tls->next;
|
||||
}
|
||||
|
||||
*pm = m;
|
||||
pm = &m->next;
|
||||
}
|
||||
|
||||
/* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME
|
||||
@ -3618,6 +3658,20 @@ Error: First section in segment (%s) starts at 0x%x whereas the segment starts a
|
||||
if ((flags & SEC_LOAD) != 0)
|
||||
p->p_filesz += sec->_raw_size;
|
||||
|
||||
if (p->p_type == PT_TLS
|
||||
&& sec->_raw_size == 0
|
||||
&& (sec->flags & SEC_HAS_CONTENTS) == 0)
|
||||
{
|
||||
struct bfd_link_order *o;
|
||||
bfd_vma tbss_size = 0;
|
||||
|
||||
for (o = sec->link_order_head; o != NULL; o = o->next)
|
||||
if (tbss_size < o->offset + o->size)
|
||||
tbss_size = o->offset + o->size;
|
||||
|
||||
p->p_memsz += tbss_size;
|
||||
}
|
||||
|
||||
if (align > p->p_align
|
||||
&& (p->p_type != PT_LOAD || (abfd->flags & D_PAGED) == 0))
|
||||
p->p_align = align;
|
||||
@ -3752,6 +3806,16 @@ get_program_header_size (abfd)
|
||||
}
|
||||
}
|
||||
|
||||
for (s = abfd->sections; s != NULL; s = s->next)
|
||||
{
|
||||
if (s->flags & SEC_THREAD_LOCAL)
|
||||
{
|
||||
/* We need a PT_TLS segment. */
|
||||
++segs;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Let the backend count up any program headers it might need. */
|
||||
if (bed->elf_backend_additional_program_headers)
|
||||
{
|
||||
@ -5045,13 +5109,18 @@ swap_out_syms (abfd, sttp, relocatable_p)
|
||||
sym.st_shndx = shndx;
|
||||
}
|
||||
|
||||
if ((flags & BSF_FUNCTION) != 0)
|
||||
if ((flags & BSF_THREAD_LOCAL) != 0)
|
||||
type = STT_TLS;
|
||||
else if ((flags & BSF_FUNCTION) != 0)
|
||||
type = STT_FUNC;
|
||||
else if ((flags & BSF_OBJECT) != 0)
|
||||
type = STT_OBJECT;
|
||||
else
|
||||
type = STT_NOTYPE;
|
||||
|
||||
if (syms[idx]->section->flags & SEC_THREAD_LOCAL)
|
||||
type = STT_TLS;
|
||||
|
||||
/* Processor-specific types */
|
||||
if (type_ptr != NULL
|
||||
&& bed->elf_backend_get_symbol_type)
|
||||
|
662
bfd/elf32-i386.c
662
bfd/elf32-i386.c
@ -46,6 +46,13 @@ static boolean elf_i386_create_dynamic_sections
|
||||
PARAMS((bfd *, struct bfd_link_info *));
|
||||
static void elf_i386_copy_indirect_symbol
|
||||
PARAMS ((struct elf_link_hash_entry *, struct elf_link_hash_entry *));
|
||||
static int elf_i386_tls_transition
|
||||
PARAMS ((struct bfd_link_info *, int, int));
|
||||
|
||||
static boolean elf_i386_mkobject
|
||||
PARAMS((bfd *));
|
||||
static boolean elf_i386_object_p
|
||||
PARAMS((bfd *));
|
||||
static boolean elf_i386_check_relocs
|
||||
PARAMS ((bfd *, struct bfd_link_info *, asection *,
|
||||
const Elf_Internal_Rela *));
|
||||
@ -65,6 +72,10 @@ static boolean elf_i386_fake_sections
|
||||
PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *));
|
||||
static boolean elf_i386_size_dynamic_sections
|
||||
PARAMS ((bfd *, struct bfd_link_info *));
|
||||
static bfd_vma dtpoff_base
|
||||
PARAMS ((struct bfd_link_info *));
|
||||
static bfd_vma tpoff
|
||||
PARAMS ((struct bfd_link_info *, bfd_vma));
|
||||
static boolean elf_i386_relocate_section
|
||||
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
|
||||
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
|
||||
@ -121,9 +132,18 @@ static reloc_howto_type elf_howto_table[]=
|
||||
R_386_ext_offset is the value to subtract from a reloc type of
|
||||
R_386_16 thru R_386_PC8 to form an index into this table. */
|
||||
#define R_386_standard ((unsigned int) R_386_GOTPC + 1)
|
||||
#define R_386_ext_offset ((unsigned int) R_386_16 - R_386_standard)
|
||||
#define R_386_ext_offset ((unsigned int) R_386_TLS_LE - R_386_standard)
|
||||
|
||||
/* The remaining relocs are a GNU extension. */
|
||||
HOWTO(R_386_TLS_LE, 0, 2, 32, false, 0, complain_overflow_bitfield,
|
||||
bfd_elf_generic_reloc, "R_386_TLS_LE",
|
||||
true, 0xffffffff, 0xffffffff, false),
|
||||
HOWTO(R_386_TLS_GD, 0, 2, 32, false, 0, complain_overflow_bitfield,
|
||||
bfd_elf_generic_reloc, "R_386_TLS_GD",
|
||||
true, 0xffffffff, 0xffffffff, false),
|
||||
HOWTO(R_386_TLS_LDM, 0, 2, 32, false, 0, complain_overflow_bitfield,
|
||||
bfd_elf_generic_reloc, "R_386_TLS_LDM",
|
||||
true, 0xffffffff, 0xffffffff, false),
|
||||
HOWTO(R_386_16, 0, 1, 16, false, 0, complain_overflow_bitfield,
|
||||
bfd_elf_generic_reloc, "R_386_16",
|
||||
true, 0xffff, 0xffff, false),
|
||||
@ -137,9 +157,31 @@ static reloc_howto_type elf_howto_table[]=
|
||||
bfd_elf_generic_reloc, "R_386_PC8",
|
||||
true, 0xff, 0xff, true),
|
||||
|
||||
/* Another gap. */
|
||||
#define R_386_ext ((unsigned int) R_386_PC8 + 1 - R_386_ext_offset)
|
||||
#define R_386_vt_offset ((unsigned int) R_386_GNU_VTINHERIT - R_386_ext)
|
||||
#define R_386_tls_offset ((unsigned int) R_386_TLS_LDO_32 - R_386_ext)
|
||||
/* These are common with Solaris TLS implementation. */
|
||||
HOWTO(R_386_TLS_LDO_32, 0, 2, 32, false, 0, complain_overflow_bitfield,
|
||||
bfd_elf_generic_reloc, "R_386_TLS_LDO_32",
|
||||
true, 0xffffffff, 0xffffffff, false),
|
||||
HOWTO(R_386_TLS_IE_32, 0, 2, 32, false, 0, complain_overflow_bitfield,
|
||||
bfd_elf_generic_reloc, "R_386_TLS_IE_32",
|
||||
true, 0xffffffff, 0xffffffff, false),
|
||||
HOWTO(R_386_TLS_LE_32, 0, 2, 32, false, 0, complain_overflow_bitfield,
|
||||
bfd_elf_generic_reloc, "R_386_TLS_LE_32",
|
||||
true, 0xffffffff, 0xffffffff, false),
|
||||
HOWTO(R_386_TLS_DTPMOD32, 0, 2, 32, false, 0, complain_overflow_bitfield,
|
||||
bfd_elf_generic_reloc, "R_386_TLS_DTPMOD32",
|
||||
true, 0xffffffff, 0xffffffff, false),
|
||||
HOWTO(R_386_TLS_DTPOFF32, 0, 2, 32, false, 0, complain_overflow_bitfield,
|
||||
bfd_elf_generic_reloc, "R_386_TLS_DTPOFF32",
|
||||
true, 0xffffffff, 0xffffffff, false),
|
||||
HOWTO(R_386_TLS_TPOFF32, 0, 2, 32, false, 0, complain_overflow_bitfield,
|
||||
bfd_elf_generic_reloc, "R_386_TLS_TPOFF32",
|
||||
true, 0xffffffff, 0xffffffff, false),
|
||||
|
||||
/* Another gap. */
|
||||
#define R_386_tls ((unsigned int) R_386_TLS_TPOFF32 + 1 - R_386_tls_offset)
|
||||
#define R_386_vt_offset ((unsigned int) R_386_GNU_VTINHERIT - R_386_tls)
|
||||
|
||||
/* GNU extension to record C++ vtable hierarchy. */
|
||||
HOWTO (R_386_GNU_VTINHERIT, /* type */
|
||||
@ -237,6 +279,18 @@ elf_i386_reloc_type_lookup (abfd, code)
|
||||
return &elf_howto_table[(unsigned int) R_386_GOTPC ];
|
||||
|
||||
/* The remaining relocs are a GNU extension. */
|
||||
case BFD_RELOC_386_TLS_LE:
|
||||
TRACE ("BFD_RELOC_386_TLS_LE");
|
||||
return &elf_howto_table[(unsigned int) R_386_TLS_LE - R_386_ext_offset];
|
||||
|
||||
case BFD_RELOC_386_TLS_GD:
|
||||
TRACE ("BFD_RELOC_386_TLS_GD");
|
||||
return &elf_howto_table[(unsigned int) R_386_TLS_GD - R_386_ext_offset];
|
||||
|
||||
case BFD_RELOC_386_TLS_LDM:
|
||||
TRACE ("BFD_RELOC_386_TLS_LDM");
|
||||
return &elf_howto_table[(unsigned int) R_386_TLS_LDM - R_386_ext_offset];
|
||||
|
||||
case BFD_RELOC_16:
|
||||
TRACE ("BFD_RELOC_16");
|
||||
return &elf_howto_table[(unsigned int) R_386_16 - R_386_ext_offset];
|
||||
@ -253,6 +307,31 @@ elf_i386_reloc_type_lookup (abfd, code)
|
||||
TRACE ("BFD_RELOC_8_PCREL");
|
||||
return &elf_howto_table[(unsigned int) R_386_PC8 - R_386_ext_offset];
|
||||
|
||||
/* Common with Sun TLS implementation. */
|
||||
case BFD_RELOC_386_TLS_LDO_32:
|
||||
TRACE ("BFD_RELOC_386_TLS_LDO_32");
|
||||
return &elf_howto_table[(unsigned int) R_386_TLS_LDO_32 - R_386_tls_offset];
|
||||
|
||||
case BFD_RELOC_386_TLS_IE_32:
|
||||
TRACE ("BFD_RELOC_386_TLS_IE_32");
|
||||
return &elf_howto_table[(unsigned int) R_386_TLS_IE_32 - R_386_tls_offset];
|
||||
|
||||
case BFD_RELOC_386_TLS_LE_32:
|
||||
TRACE ("BFD_RELOC_386_TLS_LE_32");
|
||||
return &elf_howto_table[(unsigned int) R_386_TLS_LE_32 - R_386_tls_offset];
|
||||
|
||||
case BFD_RELOC_386_TLS_DTPMOD32:
|
||||
TRACE ("BFD_RELOC_386_TLS_DTPMOD32");
|
||||
return &elf_howto_table[(unsigned int) R_386_TLS_DTPMOD32 - R_386_tls_offset];
|
||||
|
||||
case BFD_RELOC_386_TLS_DTPOFF32:
|
||||
TRACE ("BFD_RELOC_386_TLS_DTPOFF32");
|
||||
return &elf_howto_table[(unsigned int) R_386_TLS_DTPOFF32 - R_386_tls_offset];
|
||||
|
||||
case BFD_RELOC_386_TLS_TPOFF32:
|
||||
TRACE ("BFD_RELOC_386_TLS_TPOFF32");
|
||||
return &elf_howto_table[(unsigned int) R_386_TLS_TPOFF32 - R_386_tls_offset];
|
||||
|
||||
case BFD_RELOC_VTABLE_INHERIT:
|
||||
TRACE ("BFD_RELOC_VTABLE_INHERIT");
|
||||
return &elf_howto_table[(unsigned int) R_386_GNU_VTINHERIT
|
||||
@ -292,8 +371,10 @@ elf_i386_info_to_howto_rel (abfd, cache_ptr, dst)
|
||||
if ((indx = r_type) >= R_386_standard
|
||||
&& ((indx = r_type - R_386_ext_offset) - R_386_standard
|
||||
>= R_386_ext - R_386_standard)
|
||||
&& ((indx = r_type - R_386_vt_offset) - R_386_ext
|
||||
>= R_386_vt - R_386_ext))
|
||||
&& ((indx = r_type - R_386_tls_offset) - R_386_ext
|
||||
>= R_386_tls - R_386_ext)
|
||||
&& ((indx = r_type - R_386_vt_offset) - R_386_tls
|
||||
>= R_386_vt - R_386_tls))
|
||||
{
|
||||
(*_bfd_error_handler) (_("%s: invalid relocation type %d"),
|
||||
bfd_archive_filename (abfd), (int) r_type);
|
||||
@ -481,8 +562,54 @@ struct elf_i386_link_hash_entry
|
||||
|
||||
/* Track dynamic relocs copied for this symbol. */
|
||||
struct elf_i386_dyn_relocs *dyn_relocs;
|
||||
|
||||
enum {
|
||||
GOT_UNKNOWN = 0, GOT_NORMAL, GOT_TLS_GD, GOT_TLS_IE
|
||||
} tls_type;
|
||||
};
|
||||
|
||||
#define elf_i386_hash_entry(ent) ((struct elf_i386_link_hash_entry *)(ent))
|
||||
|
||||
struct elf_i386_obj_tdata
|
||||
{
|
||||
struct elf_obj_tdata root;
|
||||
|
||||
/* tls_type for each local got entry. */
|
||||
char *local_got_tls_type;
|
||||
};
|
||||
|
||||
#define elf_i386_tdata(abfd) \
|
||||
((struct elf_i386_obj_tdata *) (abfd)->tdata.any)
|
||||
|
||||
#define elf_i386_local_got_tls_type(abfd) \
|
||||
(elf_i386_tdata (abfd)->local_got_tls_type)
|
||||
|
||||
static boolean
|
||||
elf_i386_mkobject (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
bfd_size_type amt = sizeof (struct elf_i386_obj_tdata);
|
||||
abfd->tdata.any = bfd_zalloc (abfd, amt);
|
||||
if (abfd->tdata.any == NULL)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean
|
||||
elf_i386_object_p (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
/* Allocate our special target data. */
|
||||
struct elf_i386_obj_tdata *new_tdata;
|
||||
bfd_size_type amt = sizeof (struct elf_i386_obj_tdata);
|
||||
new_tdata = bfd_zalloc (abfd, amt);
|
||||
if (new_tdata == NULL)
|
||||
return false;
|
||||
new_tdata->root = *abfd->tdata.elf_obj_data;
|
||||
abfd->tdata.any = new_tdata;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* i386 ELF linker hash table. */
|
||||
|
||||
struct elf_i386_link_hash_table
|
||||
@ -498,6 +625,11 @@ struct elf_i386_link_hash_table
|
||||
asection *sdynbss;
|
||||
asection *srelbss;
|
||||
|
||||
union {
|
||||
bfd_signed_vma refcount;
|
||||
bfd_vma offset;
|
||||
} tls_ldm_got;
|
||||
|
||||
/* Small local sym to section mapping cache. */
|
||||
struct sym_sec_cache sym_sec;
|
||||
};
|
||||
@ -533,6 +665,7 @@ link_hash_newfunc (entry, table, string)
|
||||
|
||||
eh = (struct elf_i386_link_hash_entry *) entry;
|
||||
eh->dyn_relocs = NULL;
|
||||
eh->tls_type = GOT_UNKNOWN;
|
||||
}
|
||||
|
||||
return entry;
|
||||
@ -678,6 +811,29 @@ elf_i386_copy_indirect_symbol (dir, ind)
|
||||
_bfd_elf_link_hash_copy_indirect (dir, ind);
|
||||
}
|
||||
|
||||
static int
|
||||
elf_i386_tls_transition (info, r_type, is_local)
|
||||
struct bfd_link_info *info;
|
||||
int r_type;
|
||||
int is_local;
|
||||
{
|
||||
if (info->shared)
|
||||
return r_type;
|
||||
|
||||
switch (r_type)
|
||||
{
|
||||
case R_386_TLS_GD:
|
||||
case R_386_TLS_IE_32:
|
||||
if (is_local)
|
||||
return R_386_TLS_LE_32;
|
||||
return R_386_TLS_IE_32;
|
||||
case R_386_TLS_LDM:
|
||||
return R_386_TLS_LE_32;
|
||||
}
|
||||
|
||||
return r_type;
|
||||
}
|
||||
|
||||
/* Look through the relocs for a section during the first phase, and
|
||||
calculate needed space in the global offset table, procedure linkage
|
||||
table, and dynamic reloc sections. */
|
||||
@ -708,10 +864,12 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
||||
rel_end = relocs + sec->reloc_count;
|
||||
for (rel = relocs; rel < rel_end; rel++)
|
||||
{
|
||||
unsigned int r_type;
|
||||
unsigned long r_symndx;
|
||||
struct elf_link_hash_entry *h;
|
||||
|
||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||
r_type = ELF32_R_TYPE (rel->r_info);
|
||||
|
||||
if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
|
||||
{
|
||||
@ -726,13 +884,32 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
||||
else
|
||||
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
||||
|
||||
switch (ELF32_R_TYPE (rel->r_info))
|
||||
r_type = elf_i386_tls_transition (info, r_type, h == NULL);
|
||||
|
||||
switch (r_type)
|
||||
{
|
||||
case R_386_TLS_IE_32:
|
||||
if (info->shared)
|
||||
info->flags |= DF_STATIC_TLS;
|
||||
/* FALLTHROUGH */
|
||||
case R_386_GOT32:
|
||||
case R_386_TLS_GD:
|
||||
/* This symbol requires a global offset table entry. */
|
||||
{
|
||||
int tls_type, old_tls_type;
|
||||
|
||||
switch (r_type)
|
||||
{
|
||||
default:
|
||||
case R_386_GOT32: tls_type = GOT_NORMAL; break;
|
||||
case R_386_TLS_GD: tls_type = GOT_TLS_GD; break;
|
||||
case R_386_TLS_IE_32: tls_type = GOT_TLS_IE; break;
|
||||
}
|
||||
|
||||
if (h != NULL)
|
||||
{
|
||||
h->got.refcount += 1;
|
||||
old_tls_type = elf_i386_hash_entry(h)->tls_type;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -745,19 +922,48 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
||||
bfd_size_type size;
|
||||
|
||||
size = symtab_hdr->sh_info;
|
||||
size *= sizeof (bfd_signed_vma);
|
||||
size *= (sizeof (bfd_signed_vma) + sizeof(char));
|
||||
local_got_refcounts = ((bfd_signed_vma *)
|
||||
bfd_zalloc (abfd, size));
|
||||
if (local_got_refcounts == NULL)
|
||||
return false;
|
||||
elf_local_got_refcounts (abfd) = local_got_refcounts;
|
||||
elf_i386_local_got_tls_type (abfd)
|
||||
= (char *) (local_got_refcounts + symtab_hdr->sh_info);
|
||||
}
|
||||
local_got_refcounts[r_symndx] += 1;
|
||||
old_tls_type = elf_i386_local_got_tls_type (abfd) [r_symndx];
|
||||
}
|
||||
|
||||
/* If a TLS symbol is accessed using IE at least once,
|
||||
there is no point to use dynamic model for it. */
|
||||
if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN
|
||||
&& (old_tls_type != GOT_TLS_GD || tls_type != GOT_TLS_IE))
|
||||
{
|
||||
if (old_tls_type == GOT_TLS_IE && tls_type == GOT_TLS_GD)
|
||||
tls_type = GOT_TLS_IE;
|
||||
else
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("%s: `%s' accessed both as normal and thread local symbol"),
|
||||
bfd_archive_filename (abfd), h->root.root.string);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (old_tls_type != tls_type)
|
||||
{
|
||||
if (h != NULL)
|
||||
elf_i386_hash_entry (h)->tls_type = tls_type;
|
||||
else
|
||||
elf_i386_local_got_tls_type (abfd) [r_symndx] = tls_type;
|
||||
}
|
||||
}
|
||||
/* Fall through */
|
||||
|
||||
case R_386_GOTOFF:
|
||||
case R_386_GOTPC:
|
||||
create_got:
|
||||
if (htab->sgot == NULL)
|
||||
{
|
||||
if (htab->elf.dynobj == NULL)
|
||||
@ -767,6 +973,10 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
||||
}
|
||||
break;
|
||||
|
||||
case R_386_TLS_LDM:
|
||||
htab->tls_ldm_got.refcount += 1;
|
||||
goto create_got;
|
||||
|
||||
case R_386_PLT32:
|
||||
/* This symbol requires a procedure linkage table entry. We
|
||||
actually build the entry in adjust_dynamic_symbol,
|
||||
@ -824,7 +1034,7 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
||||
symbol. */
|
||||
if ((info->shared
|
||||
&& (sec->flags & SEC_ALLOC) != 0
|
||||
&& (ELF32_R_TYPE (rel->r_info) != R_386_PC32
|
||||
&& (r_type != R_386_PC32
|
||||
|| (h != NULL
|
||||
&& (! info->symbolic
|
||||
|| h->root.type == bfd_link_hash_defweak
|
||||
@ -923,7 +1133,7 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
||||
}
|
||||
|
||||
p->count += 1;
|
||||
if (ELF32_R_TYPE (rel->r_info) == R_386_PC32)
|
||||
if (r_type == R_386_PC32)
|
||||
p->pc_count += 1;
|
||||
}
|
||||
break;
|
||||
@ -942,6 +1152,16 @@ elf_i386_check_relocs (abfd, info, sec, relocs)
|
||||
return false;
|
||||
break;
|
||||
|
||||
case R_386_TLS_LE_32:
|
||||
case R_386_TLS_LE:
|
||||
if (info->shared)
|
||||
{
|
||||
(*_bfd_error_handler) (_("%s: TLS local exec code cannot be linked into shared objects"),
|
||||
bfd_archive_filename (abfd));
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1016,11 +1236,18 @@ elf_i386_gc_sweep_hook (abfd, info, sec, relocs)
|
||||
|
||||
relend = relocs + sec->reloc_count;
|
||||
for (rel = relocs; rel < relend; rel++)
|
||||
switch (ELF32_R_TYPE (rel->r_info))
|
||||
switch (elf_i386_tls_transition (info, ELF32_R_TYPE (rel->r_info),
|
||||
ELF32_R_SYM (rel->r_info)
|
||||
>= symtab_hdr->sh_info))
|
||||
{
|
||||
case R_386_TLS_LDM:
|
||||
if (elf_i386_hash_table (info)->tls_ldm_got.refcount > 0)
|
||||
elf_i386_hash_table (info)->tls_ldm_got.refcount -= 1;
|
||||
break;
|
||||
|
||||
case R_386_TLS_GD:
|
||||
case R_386_TLS_IE_32:
|
||||
case R_386_GOT32:
|
||||
case R_386_GOTOFF:
|
||||
case R_386_GOTPC:
|
||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||
if (r_symndx >= symtab_hdr->sh_info)
|
||||
{
|
||||
@ -1319,10 +1546,18 @@ allocate_dynrelocs (h, inf)
|
||||
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
|
||||
}
|
||||
|
||||
if (h->got.refcount > 0)
|
||||
/* If R_386_TLS_IE_32 symbol is now local to the binary,
|
||||
make it a R_386_TLS_LE_32 requiring no TLS entry. */
|
||||
if (h->got.refcount > 0
|
||||
&& !info->shared
|
||||
&& h->dynindx == -1
|
||||
&& elf_i386_hash_entry(h)->tls_type == GOT_TLS_IE)
|
||||
h->got.offset = (bfd_vma) -1;
|
||||
else if (h->got.refcount > 0)
|
||||
{
|
||||
asection *s;
|
||||
boolean dyn;
|
||||
int tls_type = elf_i386_hash_entry(h)->tls_type;
|
||||
|
||||
/* Make sure this symbol is output as a dynamic symbol.
|
||||
Undefined weak syms won't yet be marked as dynamic. */
|
||||
@ -1336,8 +1571,18 @@ allocate_dynrelocs (h, inf)
|
||||
s = htab->sgot;
|
||||
h->got.offset = s->_raw_size;
|
||||
s->_raw_size += 4;
|
||||
/* R_386_TLS_GD needs 2 consecutive GOT slots. */
|
||||
if (tls_type == GOT_TLS_GD)
|
||||
s->_raw_size += 4;
|
||||
dyn = htab->elf.dynamic_sections_created;
|
||||
if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
|
||||
/* R_386_TLS_IE_32 needs one dynamic relocation,
|
||||
R_386_TLS_GD needs one if local symbol and two if global. */
|
||||
if ((tls_type == GOT_TLS_GD && h->dynindx == -1)
|
||||
|| tls_type == GOT_TLS_IE)
|
||||
htab->srelgot->_raw_size += sizeof (Elf32_External_Rel);
|
||||
else if (tls_type == GOT_TLS_GD)
|
||||
htab->srelgot->_raw_size += 2 * sizeof (Elf32_External_Rel);
|
||||
else if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
|
||||
htab->srelgot->_raw_size += sizeof (Elf32_External_Rel);
|
||||
}
|
||||
else
|
||||
@ -1483,6 +1728,7 @@ elf_i386_size_dynamic_sections (output_bfd, info)
|
||||
{
|
||||
bfd_signed_vma *local_got;
|
||||
bfd_signed_vma *end_local_got;
|
||||
char *local_tls_type;
|
||||
bfd_size_type locsymcount;
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
asection *srel;
|
||||
@ -1524,15 +1770,20 @@ elf_i386_size_dynamic_sections (output_bfd, info)
|
||||
symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
|
||||
locsymcount = symtab_hdr->sh_info;
|
||||
end_local_got = local_got + locsymcount;
|
||||
local_tls_type = elf_i386_local_got_tls_type (ibfd);
|
||||
s = htab->sgot;
|
||||
srel = htab->srelgot;
|
||||
for (; local_got < end_local_got; ++local_got)
|
||||
for (; local_got < end_local_got; ++local_got, ++local_tls_type)
|
||||
{
|
||||
if (*local_got > 0)
|
||||
{
|
||||
*local_got = s->_raw_size;
|
||||
s->_raw_size += 4;
|
||||
if (info->shared)
|
||||
if (*local_tls_type == GOT_TLS_GD)
|
||||
s->_raw_size += 4;
|
||||
if (info->shared
|
||||
|| *local_tls_type == GOT_TLS_GD
|
||||
|| *local_tls_type == GOT_TLS_IE)
|
||||
srel->_raw_size += sizeof (Elf32_External_Rel);
|
||||
}
|
||||
else
|
||||
@ -1540,6 +1791,17 @@ elf_i386_size_dynamic_sections (output_bfd, info)
|
||||
}
|
||||
}
|
||||
|
||||
if (htab->tls_ldm_got.refcount > 0)
|
||||
{
|
||||
/* Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM
|
||||
relocs. */
|
||||
htab->tls_ldm_got.offset = htab->sgot->_raw_size;
|
||||
htab->sgot->_raw_size += 8;
|
||||
htab->srelgot->_raw_size += sizeof (Elf32_External_Rel);
|
||||
}
|
||||
else
|
||||
htab->tls_ldm_got.offset = -1;
|
||||
|
||||
/* Allocate global sym .plt and .got entries, and space for global
|
||||
sym dynamic relocs. */
|
||||
elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
|
||||
@ -1685,6 +1947,34 @@ elf_i386_fake_sections (abfd, hdr, sec)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Return the base VMA address which should be subtracted from real addresses
|
||||
when resolving @dtpoff relocation.
|
||||
This is PT_TLS segment p_vaddr. */
|
||||
|
||||
static bfd_vma
|
||||
dtpoff_base (info)
|
||||
struct bfd_link_info *info;
|
||||
{
|
||||
BFD_ASSERT (elf_hash_table (info)->tls_segment != NULL);
|
||||
return elf_hash_table (info)->tls_segment->start;
|
||||
}
|
||||
|
||||
/* Return the relocation value for @tpoff relocation
|
||||
if STT_TLS virtual address is ADDRESS. */
|
||||
|
||||
static bfd_vma
|
||||
tpoff (info, address)
|
||||
struct bfd_link_info *info;
|
||||
bfd_vma address;
|
||||
{
|
||||
struct elf_link_tls_segment *tls_segment
|
||||
= elf_hash_table (info)->tls_segment;
|
||||
|
||||
BFD_ASSERT (tls_segment != NULL);
|
||||
return (align_power (tls_segment->size, tls_segment->align)
|
||||
+ tls_segment->start - address);
|
||||
}
|
||||
|
||||
/* Relocate an i386 ELF section. */
|
||||
|
||||
static boolean
|
||||
@ -1715,7 +2005,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
relend = relocs + input_section->reloc_count;
|
||||
for (; rel < relend; rel++)
|
||||
{
|
||||
int r_type;
|
||||
unsigned int r_type;
|
||||
reloc_howto_type *howto;
|
||||
unsigned long r_symndx;
|
||||
struct elf_link_hash_entry *h;
|
||||
@ -1726,6 +2016,7 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
boolean unresolved_reloc;
|
||||
bfd_reloc_status_type r;
|
||||
unsigned int indx;
|
||||
int tls_type;
|
||||
|
||||
r_type = ELF32_R_TYPE (rel->r_info);
|
||||
if (r_type == (int) R_386_GNU_VTINHERIT
|
||||
@ -1733,8 +2024,10 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
continue;
|
||||
|
||||
if ((indx = (unsigned) r_type) >= R_386_standard
|
||||
&& ((indx = (unsigned) r_type - R_386_ext_offset) - R_386_standard
|
||||
>= R_386_ext - R_386_standard))
|
||||
&& ((indx = r_type - R_386_ext_offset) - R_386_standard
|
||||
>= R_386_ext - R_386_standard)
|
||||
&& ((indx = r_type - R_386_tls_offset) - R_386_ext
|
||||
>= R_386_tls - R_386_ext))
|
||||
{
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return false;
|
||||
@ -2118,6 +2411,330 @@ elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
}
|
||||
break;
|
||||
|
||||
case R_386_TLS_GD:
|
||||
case R_386_TLS_IE_32:
|
||||
r_type = elf_i386_tls_transition (info, r_type, h == NULL);
|
||||
tls_type = GOT_UNKNOWN;
|
||||
if (h == NULL && local_got_offsets)
|
||||
tls_type = elf_i386_local_got_tls_type (input_bfd) [r_symndx];
|
||||
else if (h != NULL)
|
||||
{
|
||||
tls_type = elf_i386_hash_entry(h)->tls_type;
|
||||
if (!info->shared && h->dynindx == -1 && tls_type == GOT_TLS_IE)
|
||||
r_type = R_386_TLS_LE_32;
|
||||
}
|
||||
if (r_type == R_386_TLS_GD && tls_type == GOT_TLS_IE)
|
||||
r_type = R_386_TLS_IE_32;
|
||||
|
||||
if (r_type == R_386_TLS_LE_32)
|
||||
{
|
||||
BFD_ASSERT (unresolved_reloc == false);
|
||||
if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD)
|
||||
{
|
||||
unsigned int val, type;
|
||||
bfd_vma roff;
|
||||
|
||||
/* GD->LE transition. */
|
||||
BFD_ASSERT (rel->r_offset >= 2);
|
||||
type = bfd_get_8 (input_bfd, contents + rel->r_offset - 2);
|
||||
BFD_ASSERT (type == 0x8d || type == 0x04);
|
||||
BFD_ASSERT (rel->r_offset + 9 <= input_section->_raw_size);
|
||||
BFD_ASSERT (bfd_get_8 (input_bfd,
|
||||
contents + rel->r_offset + 4)
|
||||
== 0xe8);
|
||||
BFD_ASSERT (rel + 1 < relend);
|
||||
BFD_ASSERT (ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32);
|
||||
roff = rel->r_offset + 5;
|
||||
val = bfd_get_8 (input_bfd,
|
||||
contents + rel->r_offset - 1);
|
||||
if (type == 0x04)
|
||||
{
|
||||
/* leal foo(,%reg,1), %eax; call ___tls_get_addr
|
||||
Change it into:
|
||||
movl %gs:0, %eax; subl $foo@tpoff, %eax
|
||||
(6 byte form of subl). */
|
||||
BFD_ASSERT (rel->r_offset >= 3);
|
||||
BFD_ASSERT (bfd_get_8 (input_bfd,
|
||||
contents + rel->r_offset - 3)
|
||||
== 0x8d);
|
||||
BFD_ASSERT ((val & 0xc7) == 0x05 && val != (4 << 3));
|
||||
memcpy (contents + rel->r_offset - 3,
|
||||
"\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12);
|
||||
}
|
||||
else
|
||||
{
|
||||
BFD_ASSERT ((val & 0xf8) == 0x80 && (val & 7) != 4);
|
||||
if (rel->r_offset + 10 <= input_section->_raw_size
|
||||
&& bfd_get_8 (input_bfd,
|
||||
contents + rel->r_offset + 9) == 0x90)
|
||||
{
|
||||
/* leal foo(%reg), %eax; call ___tls_get_addr; nop
|
||||
Change it into:
|
||||
movl %gs:0, %eax; subl $foo@tpoff, %eax
|
||||
(6 byte form of subl). */
|
||||
memcpy (contents + rel->r_offset - 2,
|
||||
"\x65\xa1\0\0\0\0\x81\xe8\0\0\0", 12);
|
||||
roff = rel->r_offset + 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* leal foo(%reg), %eax; call ___tls_get_addr
|
||||
Change it into:
|
||||
movl %gs:0, %eax; subl $foo@tpoff, %eax
|
||||
(5 byte form of subl). */
|
||||
memcpy (contents + rel->r_offset - 2,
|
||||
"\x65\xa1\0\0\0\0\x2d\0\0\0", 11);
|
||||
}
|
||||
}
|
||||
bfd_put_32 (output_bfd, tpoff (info, relocation),
|
||||
contents + roff);
|
||||
/* Skip R_386_PLT32. */
|
||||
rel++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int val, type;
|
||||
|
||||
/* IE->LE transition:
|
||||
Originally it can be either:
|
||||
subl foo(%reg1), %reg2
|
||||
or
|
||||
movl foo(%reg1), %reg2
|
||||
We change it into:
|
||||
subl $foo, %reg2
|
||||
or
|
||||
movl $foo, %reg2 (6 byte form) */
|
||||
BFD_ASSERT (rel->r_offset >= 2);
|
||||
type = bfd_get_8 (input_bfd, contents + rel->r_offset - 2);
|
||||
val = bfd_get_8 (input_bfd, contents + rel->r_offset - 1);
|
||||
BFD_ASSERT (rel->r_offset + 4 <= input_section->_raw_size);
|
||||
if (type == 0x8b)
|
||||
{
|
||||
/* movl */
|
||||
BFD_ASSERT ((val & 0xc0) == 0x80 && (val & 7) != 4);
|
||||
bfd_put_8 (output_bfd, 0xc7,
|
||||
contents + rel->r_offset - 2);
|
||||
bfd_put_8 (output_bfd, 0xc0 | ((val >> 3) & 7),
|
||||
contents + rel->r_offset - 1);
|
||||
}
|
||||
else if (type == 0x2b)
|
||||
{
|
||||
/* subl */
|
||||
BFD_ASSERT ((val & 0xc0) == 0x80 && (val & 7) != 4);
|
||||
bfd_put_8 (output_bfd, 0x81,
|
||||
contents + rel->r_offset - 2);
|
||||
bfd_put_8 (output_bfd, 0xe8 | ((val >> 3) & 7),
|
||||
contents + rel->r_offset - 1);
|
||||
}
|
||||
else
|
||||
BFD_FAIL ();
|
||||
bfd_put_32 (output_bfd, tpoff (info, relocation),
|
||||
contents + rel->r_offset);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (htab->sgot == NULL)
|
||||
abort ();
|
||||
|
||||
if (h != NULL)
|
||||
off = h->got.offset;
|
||||
else
|
||||
{
|
||||
if (local_got_offsets == NULL)
|
||||
abort ();
|
||||
|
||||
off = local_got_offsets[r_symndx];
|
||||
}
|
||||
|
||||
if ((off & 1) != 0)
|
||||
off &= ~1;
|
||||
else
|
||||
{
|
||||
Elf_Internal_Rel outrel;
|
||||
Elf32_External_Rel *loc;
|
||||
int dr_type, indx;
|
||||
|
||||
if (htab->srelgot == NULL)
|
||||
abort ();
|
||||
|
||||
outrel.r_offset = (htab->sgot->output_section->vma
|
||||
+ htab->sgot->output_offset + off);
|
||||
|
||||
bfd_put_32 (output_bfd, 0,
|
||||
htab->sgot->contents + off);
|
||||
indx = h && h->dynindx != -1 ? h->dynindx : 0;
|
||||
if (r_type == R_386_TLS_GD)
|
||||
dr_type = R_386_TLS_DTPMOD32;
|
||||
else
|
||||
dr_type = R_386_TLS_TPOFF32;
|
||||
outrel.r_info = ELF32_R_INFO (indx, dr_type);
|
||||
loc = (Elf32_External_Rel *) htab->srelgot->contents;
|
||||
loc += htab->srelgot->reloc_count++;
|
||||
bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
|
||||
|
||||
if (r_type == R_386_TLS_GD)
|
||||
{
|
||||
if (indx == 0)
|
||||
{
|
||||
BFD_ASSERT (unresolved_reloc == false);
|
||||
bfd_put_32 (output_bfd,
|
||||
relocation - dtpoff_base (info),
|
||||
htab->sgot->contents + off + 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
bfd_put_32 (output_bfd, 0,
|
||||
htab->sgot->contents + off + 4);
|
||||
outrel.r_info = ELF32_R_INFO (indx,
|
||||
R_386_TLS_DTPOFF32);
|
||||
outrel.r_offset += 4;
|
||||
htab->srelgot->reloc_count++;
|
||||
loc++;
|
||||
bfd_elf32_swap_reloc_out (output_bfd, &outrel,
|
||||
loc);
|
||||
}
|
||||
}
|
||||
|
||||
if (h != NULL)
|
||||
h->got.offset |= 1;
|
||||
else
|
||||
local_got_offsets[r_symndx] |= 1;
|
||||
}
|
||||
|
||||
if (off >= (bfd_vma) -2)
|
||||
abort ();
|
||||
if (r_type == ELF32_R_TYPE (rel->r_info))
|
||||
{
|
||||
relocation = htab->sgot->output_offset + off;
|
||||
unresolved_reloc = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int val, type;
|
||||
bfd_vma roff;
|
||||
|
||||
/* GD->IE transition. */
|
||||
BFD_ASSERT (rel->r_offset >= 2);
|
||||
type = bfd_get_8 (input_bfd, contents + rel->r_offset - 2);
|
||||
BFD_ASSERT (type == 0x8d || type == 0x04);
|
||||
BFD_ASSERT (rel->r_offset + 9 <= input_section->_raw_size);
|
||||
BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4)
|
||||
== 0xe8);
|
||||
BFD_ASSERT (rel + 1 < relend);
|
||||
BFD_ASSERT (ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32);
|
||||
roff = rel->r_offset - 3;
|
||||
val = bfd_get_8 (input_bfd, contents + rel->r_offset - 1);
|
||||
if (type == 0x04)
|
||||
{
|
||||
/* leal foo(,%reg,1), %eax; call ___tls_get_addr
|
||||
Change it into:
|
||||
movl %gs:0, %eax; subl $foo@gottpoff(%reg), %eax. */
|
||||
BFD_ASSERT (rel->r_offset >= 3);
|
||||
BFD_ASSERT (bfd_get_8 (input_bfd,
|
||||
contents + rel->r_offset - 3)
|
||||
== 0x8d);
|
||||
BFD_ASSERT ((val & 0xc7) == 0x05 && val != (4 << 3));
|
||||
val >>= 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* leal foo(%reg), %eax; call ___tls_get_addr; nop
|
||||
Change it into:
|
||||
movl %gs:0, %eax; subl $foo@gottpoff(%reg), %eax. */
|
||||
BFD_ASSERT (rel->r_offset + 10 <= input_section->_raw_size);
|
||||
BFD_ASSERT ((val & 0xf8) == 0x80 && (val & 7) != 4);
|
||||
BFD_ASSERT (bfd_get_8 (input_bfd,
|
||||
contents + rel->r_offset + 9)
|
||||
== 0x90);
|
||||
roff = rel->r_offset - 2;
|
||||
}
|
||||
memcpy (contents + roff,
|
||||
"\x65\xa1\0\0\0\0\x2b\x80\0\0\0", 12);
|
||||
contents[roff + 7] = 0x80 | (val & 7);
|
||||
bfd_put_32 (output_bfd, htab->sgot->output_offset + off,
|
||||
contents + roff + 8);
|
||||
/* Skip R_386_PLT32. */
|
||||
rel++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case R_386_TLS_LDM:
|
||||
if (! info->shared)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
/* LD->LE transition:
|
||||
Ensure it is:
|
||||
leal foo(%reg), %eax; call ___tls_get_addr.
|
||||
We change it into:
|
||||
movl %gs:0, %eax; nop; leal 0(%esi,1), %esi. */
|
||||
BFD_ASSERT (rel->r_offset >= 2);
|
||||
BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset - 2)
|
||||
== 0x8d);
|
||||
val = bfd_get_8 (input_bfd, contents + rel->r_offset - 1);
|
||||
BFD_ASSERT ((val & 0xf8) == 0x80 && (val & 7) != 4);
|
||||
BFD_ASSERT (rel->r_offset + 9 <= input_section->_raw_size);
|
||||
BFD_ASSERT (bfd_get_8 (input_bfd, contents + rel->r_offset + 4)
|
||||
== 0xe8);
|
||||
BFD_ASSERT (rel + 1 < relend);
|
||||
BFD_ASSERT (ELF32_R_TYPE (rel[1].r_info) == R_386_PLT32);
|
||||
memcpy (contents + rel->r_offset - 2,
|
||||
"\x65\xa1\0\0\0\0\x90\x8d\x74\x26", 11);
|
||||
/* Skip R_386_PLT32. */
|
||||
rel++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (htab->sgot == NULL)
|
||||
abort ();
|
||||
|
||||
off = htab->tls_ldm_got.offset;
|
||||
if (off & 1)
|
||||
off &= ~1;
|
||||
else
|
||||
{
|
||||
Elf_Internal_Rel outrel;
|
||||
Elf32_External_Rel *loc;
|
||||
|
||||
if (htab->srelgot == NULL)
|
||||
abort ();
|
||||
|
||||
outrel.r_offset = (htab->sgot->output_section->vma
|
||||
+ htab->sgot->output_offset + off);
|
||||
|
||||
bfd_put_32 (output_bfd, 0,
|
||||
htab->sgot->contents + off);
|
||||
bfd_put_32 (output_bfd, 0,
|
||||
htab->sgot->contents + off + 4);
|
||||
outrel.r_info = ELF32_R_INFO (0, R_386_TLS_DTPMOD32);
|
||||
loc = (Elf32_External_Rel *) htab->srelgot->contents;
|
||||
loc += htab->srelgot->reloc_count++;
|
||||
bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
|
||||
htab->tls_ldm_got.offset |= 1;
|
||||
}
|
||||
relocation = htab->sgot->output_offset + off;
|
||||
unresolved_reloc = false;
|
||||
break;
|
||||
|
||||
case R_386_TLS_LDO_32:
|
||||
if (info->shared)
|
||||
relocation -= dtpoff_base (info);
|
||||
else
|
||||
/* When converting LDO to LE, we must negate. */
|
||||
relocation = -tpoff (info, relocation);
|
||||
break;
|
||||
|
||||
case R_386_TLS_LE_32:
|
||||
relocation = tpoff (info, relocation);
|
||||
break;
|
||||
|
||||
case R_386_TLS_LE:
|
||||
relocation = -tpoff (info, relocation);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2273,7 +2890,9 @@ elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym)
|
||||
}
|
||||
}
|
||||
|
||||
if (h->got.offset != (bfd_vma) -1)
|
||||
if (h->got.offset != (bfd_vma) -1
|
||||
&& elf_i386_hash_entry(h)->tls_type != GOT_TLS_GD
|
||||
&& elf_i386_hash_entry(h)->tls_type != GOT_TLS_IE)
|
||||
{
|
||||
Elf_Internal_Rel rel;
|
||||
Elf32_External_Rel *loc;
|
||||
@ -2505,6 +3124,9 @@ elf_i386_finish_dynamic_sections (output_bfd, info)
|
||||
#define elf_info_to_howto elf_i386_info_to_howto
|
||||
#define elf_info_to_howto_rel elf_i386_info_to_howto_rel
|
||||
|
||||
#define bfd_elf32_mkobject elf_i386_mkobject
|
||||
#define elf_backend_object_p elf_i386_object_p
|
||||
|
||||
#define bfd_elf32_bfd_is_local_label_name elf_i386_is_local_label_name
|
||||
#define bfd_elf32_bfd_link_hash_table_create elf_i386_link_hash_table_create
|
||||
#define bfd_elf32_bfd_reloc_type_lookup elf_i386_reloc_type_lookup
|
||||
|
@ -1723,7 +1723,23 @@ elf_link_add_object_symbols (abfd, info)
|
||||
if (name == (const char *) NULL)
|
||||
goto error_return;
|
||||
|
||||
if (add_symbol_hook)
|
||||
if (sym.st_shndx == SHN_COMMON && ELF_ST_TYPE (sym.st_info) == STT_TLS)
|
||||
{
|
||||
asection *tcomm = bfd_get_section_by_name (abfd, ".tcommon");
|
||||
|
||||
if (tcomm == NULL)
|
||||
{
|
||||
tcomm = bfd_make_section (abfd, ".tcommon");
|
||||
if (tcomm == NULL
|
||||
|| !bfd_set_section_flags (abfd, tcomm, (SEC_ALLOC
|
||||
| SEC_IS_COMMON
|
||||
| SEC_LINKER_CREATED
|
||||
| SEC_THREAD_LOCAL)))
|
||||
goto error_return;
|
||||
}
|
||||
sec = tcomm;
|
||||
}
|
||||
else if (add_symbol_hook)
|
||||
{
|
||||
if (! (*add_symbol_hook) (abfd, info, &sym, &name, &flags, &sec,
|
||||
&value))
|
||||
@ -3457,7 +3473,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
|
||||
elf_tdata (output_bfd)->cverdefs = cdefs;
|
||||
}
|
||||
|
||||
if (info->new_dtags && info->flags)
|
||||
if ((info->new_dtags && info->flags) || (info->flags & DF_STATIC_TLS))
|
||||
{
|
||||
if (! elf_add_dynamic_entry (info, (bfd_vma) DT_FLAGS, info->flags))
|
||||
return false;
|
||||
@ -4481,6 +4497,8 @@ struct elf_final_link_info
|
||||
asection *hash_sec;
|
||||
/* symbol version section (.gnu.version). */
|
||||
asection *symver_sec;
|
||||
/* first SHF_TLS section (if any). */
|
||||
asection *first_tls_sec;
|
||||
/* Buffer large enough to hold contents of any section. */
|
||||
bfd_byte *contents;
|
||||
/* Buffer large enough to hold external relocs of any section. */
|
||||
@ -4960,6 +4978,14 @@ elf_bfd_final_link (abfd, info)
|
||||
finfo.symbuf = NULL;
|
||||
finfo.symshndxbuf = NULL;
|
||||
finfo.symbuf_count = 0;
|
||||
finfo.first_tls_sec = NULL;
|
||||
for (o = abfd->sections; o != (asection *) NULL; o = o->next)
|
||||
if ((o->flags & SEC_THREAD_LOCAL) != 0
|
||||
&& (o->flags & SEC_LOAD) != 0)
|
||||
{
|
||||
finfo.first_tls_sec = o;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Count up the number of relocations we will output for each output
|
||||
section, so that we know the sizes of the reloc sections. We
|
||||
@ -5324,6 +5350,40 @@ elf_bfd_final_link (abfd, info)
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
if (finfo.first_tls_sec)
|
||||
{
|
||||
unsigned int align = 0;
|
||||
bfd_vma base = finfo.first_tls_sec->vma, end = 0;
|
||||
asection *sec;
|
||||
|
||||
for (sec = finfo.first_tls_sec;
|
||||
sec && (sec->flags & SEC_THREAD_LOCAL);
|
||||
sec = sec->next)
|
||||
{
|
||||
bfd_vma size = sec->_raw_size;
|
||||
|
||||
if (bfd_get_section_alignment (abfd, sec) > align)
|
||||
align = bfd_get_section_alignment (abfd, sec);
|
||||
if (sec->_raw_size == 0 && (sec->flags & SEC_HAS_CONTENTS) == 0)
|
||||
{
|
||||
struct bfd_link_order *o;
|
||||
|
||||
size = 0;
|
||||
for (o = sec->link_order_head; o != NULL; o = o->next)
|
||||
if (size < o->offset + o->size)
|
||||
size = o->offset + o->size;
|
||||
}
|
||||
end = sec->vma + size;
|
||||
}
|
||||
elf_hash_table (info)->tls_segment
|
||||
= bfd_zalloc (abfd, sizeof (struct elf_link_tls_segment));
|
||||
if (elf_hash_table (info)->tls_segment == NULL)
|
||||
goto error_return;
|
||||
elf_hash_table (info)->tls_segment->start = base;
|
||||
elf_hash_table (info)->tls_segment->size = end - base;
|
||||
elf_hash_table (info)->tls_segment->align = align;
|
||||
}
|
||||
|
||||
/* Since ELF permits relocations to be against local symbols, we
|
||||
must have the local symbols available when we do the relocations.
|
||||
Since we would rather only read the local symbols once, and we
|
||||
@ -6100,7 +6160,16 @@ elf_link_output_extsym (h, data)
|
||||
addresses. */
|
||||
sym.st_value = h->root.u.def.value + input_sec->output_offset;
|
||||
if (! finfo->info->relocateable)
|
||||
{
|
||||
sym.st_value += input_sec->output_section->vma;
|
||||
if (h->type == STT_TLS)
|
||||
{
|
||||
/* STT_TLS symbols are relative to PT_TLS segment
|
||||
base. */
|
||||
BFD_ASSERT (finfo->first_tls_sec != NULL);
|
||||
sym.st_value -= finfo->first_tls_sec->vma;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -6564,7 +6633,15 @@ elf_link_input_bfd (finfo, input_bfd)
|
||||
these requirements. */
|
||||
osym.st_value += isec->output_offset;
|
||||
if (! finfo->info->relocateable)
|
||||
{
|
||||
osym.st_value += isec->output_section->vma;
|
||||
if (ELF_ST_TYPE (osym.st_info) == STT_TLS)
|
||||
{
|
||||
/* STT_TLS symbols are relative to PT_TLS segment base. */
|
||||
BFD_ASSERT (finfo->first_tls_sec != NULL);
|
||||
osym.st_value -= finfo->first_tls_sec->vma;
|
||||
}
|
||||
}
|
||||
|
||||
if (! elf_link_output_sym (finfo, name, &osym, isec))
|
||||
return false;
|
||||
@ -6899,7 +6976,16 @@ elf_link_input_bfd (finfo, input_bfd)
|
||||
|
||||
isym->st_value += sec->output_offset;
|
||||
if (! finfo->info->relocateable)
|
||||
{
|
||||
isym->st_value += osec->vma;
|
||||
if (ELF_ST_TYPE (isym->st_info) == STT_TLS)
|
||||
{
|
||||
/* STT_TLS symbols are relative to PT_TLS
|
||||
segment base. */
|
||||
BFD_ASSERT (finfo->first_tls_sec != NULL);
|
||||
isym->st_value -= finfo->first_tls_sec->vma;
|
||||
}
|
||||
}
|
||||
|
||||
finfo->indices[r_symndx]
|
||||
= bfd_get_symcount (output_bfd);
|
||||
|
272
bfd/elfxx-ia64.c
272
bfd/elfxx-ia64.c
@ -79,6 +79,9 @@ struct elfNN_ia64_dyn_sym_info
|
||||
bfd_vma pltoff_offset;
|
||||
bfd_vma plt_offset;
|
||||
bfd_vma plt2_offset;
|
||||
bfd_vma tprel_offset;
|
||||
bfd_vma dtpmod_offset;
|
||||
bfd_vma dtprel_offset;
|
||||
|
||||
/* The symbol table entry, if any, that this was derrived from. */
|
||||
struct elf_link_hash_entry *h;
|
||||
@ -97,6 +100,9 @@ struct elfNN_ia64_dyn_sym_info
|
||||
unsigned got_done : 1;
|
||||
unsigned fptr_done : 1;
|
||||
unsigned pltoff_done : 1;
|
||||
unsigned tprel_done : 1;
|
||||
unsigned dtpmod_done : 1;
|
||||
unsigned dtprel_done : 1;
|
||||
|
||||
/* True for the different kinds of linker data we want created. */
|
||||
unsigned want_got : 1;
|
||||
@ -105,6 +111,9 @@ struct elfNN_ia64_dyn_sym_info
|
||||
unsigned want_plt : 1;
|
||||
unsigned want_plt2 : 1;
|
||||
unsigned want_pltoff : 1;
|
||||
unsigned want_tprel : 1;
|
||||
unsigned want_dtpmod : 1;
|
||||
unsigned want_dtprel : 1;
|
||||
};
|
||||
|
||||
struct elfNN_ia64_local_hash_entry
|
||||
@ -285,6 +294,10 @@ static bfd_vma set_pltoff_entry
|
||||
PARAMS ((bfd *abfd, struct bfd_link_info *info,
|
||||
struct elfNN_ia64_dyn_sym_info *dyn_i,
|
||||
bfd_vma value, boolean));
|
||||
static bfd_vma elfNN_ia64_tprel_base
|
||||
PARAMS ((struct bfd_link_info *info));
|
||||
static bfd_vma elfNN_ia64_dtprel_base
|
||||
PARAMS ((struct bfd_link_info *info));
|
||||
static int elfNN_ia64_unwind_entry_compare
|
||||
PARAMS ((const PTR, const PTR));
|
||||
static boolean elfNN_ia64_final_link
|
||||
@ -423,10 +436,25 @@ static reloc_howto_type ia64_howto_table[] =
|
||||
IA64_HOWTO (R_IA64_LTOFF22X, "LTOFF22X", 0, false, true),
|
||||
IA64_HOWTO (R_IA64_LDXMOV, "LDXMOV", 0, false, true),
|
||||
|
||||
IA64_HOWTO (R_IA64_TPREL14, "TPREL14", 0, false, false),
|
||||
IA64_HOWTO (R_IA64_TPREL22, "TPREL22", 0, false, false),
|
||||
IA64_HOWTO (R_IA64_TPREL64I, "TPREL64I", 0, false, false),
|
||||
IA64_HOWTO (R_IA64_TPREL64MSB, "TPREL64MSB", 8, false, false),
|
||||
IA64_HOWTO (R_IA64_TPREL64LSB, "TPREL64LSB", 8, false, false),
|
||||
IA64_HOWTO (R_IA64_LTOFF_TP22, "LTOFF_TP22", 0, false, false),
|
||||
IA64_HOWTO (R_IA64_LTOFF_TPREL22, "LTOFF_TPREL22", 0, false, false),
|
||||
|
||||
IA64_HOWTO (R_IA64_DTPMOD64MSB, "TPREL64MSB", 8, false, false),
|
||||
IA64_HOWTO (R_IA64_DTPMOD64LSB, "TPREL64LSB", 8, false, false),
|
||||
IA64_HOWTO (R_IA64_LTOFF_DTPMOD22, "LTOFF_DTPMOD22", 0, false, false),
|
||||
|
||||
IA64_HOWTO (R_IA64_DTPREL14, "DTPREL14", 0, false, false),
|
||||
IA64_HOWTO (R_IA64_DTPREL22, "DTPREL22", 0, false, false),
|
||||
IA64_HOWTO (R_IA64_DTPREL64I, "DTPREL64I", 0, false, false),
|
||||
IA64_HOWTO (R_IA64_DTPREL32MSB, "DTPREL32MSB", 4, false, false),
|
||||
IA64_HOWTO (R_IA64_DTPREL32LSB, "DTPREL32LSB", 4, false, false),
|
||||
IA64_HOWTO (R_IA64_DTPREL64MSB, "DTPREL64MSB", 8, false, false),
|
||||
IA64_HOWTO (R_IA64_DTPREL64LSB, "DTPREL64LSB", 8, false, false),
|
||||
IA64_HOWTO (R_IA64_LTOFF_DTPREL22, "LTOFF_DTPREL22", 0, false, false),
|
||||
};
|
||||
|
||||
static unsigned char elf_code_to_howto_index[R_IA64_MAX_RELOC_CODE + 1];
|
||||
@ -541,10 +569,25 @@ elfNN_ia64_reloc_type_lookup (abfd, bfd_code)
|
||||
case BFD_RELOC_IA64_LTOFF22X: rtype = R_IA64_LTOFF22X; break;
|
||||
case BFD_RELOC_IA64_LDXMOV: rtype = R_IA64_LDXMOV; break;
|
||||
|
||||
case BFD_RELOC_IA64_TPREL14: rtype = R_IA64_TPREL14; break;
|
||||
case BFD_RELOC_IA64_TPREL22: rtype = R_IA64_TPREL22; break;
|
||||
case BFD_RELOC_IA64_TPREL64I: rtype = R_IA64_TPREL64I; break;
|
||||
case BFD_RELOC_IA64_TPREL64MSB: rtype = R_IA64_TPREL64MSB; break;
|
||||
case BFD_RELOC_IA64_TPREL64LSB: rtype = R_IA64_TPREL64LSB; break;
|
||||
case BFD_RELOC_IA64_LTOFF_TP22: rtype = R_IA64_LTOFF_TP22; break;
|
||||
case BFD_RELOC_IA64_LTOFF_TPREL22: rtype = R_IA64_LTOFF_TPREL22; break;
|
||||
|
||||
case BFD_RELOC_IA64_DTPMOD64MSB: rtype = R_IA64_DTPMOD64MSB; break;
|
||||
case BFD_RELOC_IA64_DTPMOD64LSB: rtype = R_IA64_DTPMOD64LSB; break;
|
||||
case BFD_RELOC_IA64_LTOFF_DTPMOD22: rtype = R_IA64_LTOFF_DTPMOD22; break;
|
||||
|
||||
case BFD_RELOC_IA64_DTPREL14: rtype = R_IA64_DTPREL14; break;
|
||||
case BFD_RELOC_IA64_DTPREL22: rtype = R_IA64_DTPREL22; break;
|
||||
case BFD_RELOC_IA64_DTPREL64I: rtype = R_IA64_DTPREL64I; break;
|
||||
case BFD_RELOC_IA64_DTPREL32MSB: rtype = R_IA64_DTPREL32MSB; break;
|
||||
case BFD_RELOC_IA64_DTPREL32LSB: rtype = R_IA64_DTPREL32LSB; break;
|
||||
case BFD_RELOC_IA64_DTPREL64MSB: rtype = R_IA64_DTPREL64MSB; break;
|
||||
case BFD_RELOC_IA64_DTPREL64LSB: rtype = R_IA64_DTPREL64LSB; break;
|
||||
case BFD_RELOC_IA64_LTOFF_DTPREL22: rtype = R_IA64_LTOFF_DTPREL22; break;
|
||||
|
||||
default: return 0;
|
||||
}
|
||||
@ -2097,6 +2140,9 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
|
||||
NEED_FULL_PLT = 16,
|
||||
NEED_DYNREL = 32,
|
||||
NEED_LTOFF_FPTR = 64,
|
||||
NEED_TPREL = 128,
|
||||
NEED_DTPMOD = 256,
|
||||
NEED_DTPREL = 512
|
||||
};
|
||||
|
||||
struct elf_link_hash_entry *h = NULL;
|
||||
@ -2134,11 +2180,42 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
|
||||
need_entry = 0;
|
||||
switch (ELFNN_R_TYPE (rel->r_info))
|
||||
{
|
||||
case R_IA64_TPREL22:
|
||||
case R_IA64_TPREL64MSB:
|
||||
case R_IA64_TPREL64LSB:
|
||||
case R_IA64_LTOFF_TP22:
|
||||
return false;
|
||||
if (info->shared || maybe_dynamic)
|
||||
need_entry = NEED_DYNREL;
|
||||
dynrel_type = R_IA64_TPREL64LSB;
|
||||
if (info->shared)
|
||||
info->flags |= DF_STATIC_TLS;
|
||||
break;
|
||||
|
||||
case R_IA64_LTOFF_TPREL22:
|
||||
need_entry = NEED_TPREL;
|
||||
if (info->shared)
|
||||
info->flags |= DF_STATIC_TLS;
|
||||
break;
|
||||
|
||||
case R_IA64_DTPREL64MSB:
|
||||
case R_IA64_DTPREL64LSB:
|
||||
if (info->shared || maybe_dynamic)
|
||||
need_entry = NEED_DYNREL;
|
||||
dynrel_type = R_IA64_DTPREL64LSB;
|
||||
break;
|
||||
|
||||
case R_IA64_LTOFF_DTPREL22:
|
||||
need_entry = NEED_DTPREL;
|
||||
break;
|
||||
|
||||
case R_IA64_DTPMOD64MSB:
|
||||
case R_IA64_DTPMOD64LSB:
|
||||
if (info->shared || maybe_dynamic)
|
||||
need_entry = NEED_DYNREL;
|
||||
dynrel_type = R_IA64_DTPMOD64LSB;
|
||||
break;
|
||||
|
||||
case R_IA64_LTOFF_DTPMOD22:
|
||||
need_entry = NEED_DTPMOD;
|
||||
break;
|
||||
|
||||
case R_IA64_LTOFF_FPTR22:
|
||||
case R_IA64_LTOFF_FPTR64I:
|
||||
@ -2248,7 +2325,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
|
||||
dyn_i->h = h;
|
||||
|
||||
/* Create what's needed. */
|
||||
if (need_entry & NEED_GOT)
|
||||
if (need_entry & (NEED_GOT | NEED_TPREL | NEED_DTPMOD | NEED_DTPREL))
|
||||
{
|
||||
if (!got)
|
||||
{
|
||||
@ -2256,7 +2333,14 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
|
||||
if (!got)
|
||||
return false;
|
||||
}
|
||||
if (need_entry & NEED_GOT)
|
||||
dyn_i->want_got = 1;
|
||||
if (need_entry & NEED_TPREL)
|
||||
dyn_i->want_tprel = 1;
|
||||
if (need_entry & NEED_DTPMOD)
|
||||
dyn_i->want_dtpmod = 1;
|
||||
if (need_entry & NEED_DTPREL)
|
||||
dyn_i->want_dtprel = 1;
|
||||
}
|
||||
if (need_entry & NEED_FPTR)
|
||||
{
|
||||
@ -2336,6 +2420,21 @@ allocate_global_data_got (dyn_i, data)
|
||||
dyn_i->got_offset = x->ofs;
|
||||
x->ofs += 8;
|
||||
}
|
||||
if (dyn_i->want_tprel)
|
||||
{
|
||||
dyn_i->tprel_offset = x->ofs;
|
||||
x->ofs += 8;
|
||||
}
|
||||
if (dyn_i->want_dtpmod)
|
||||
{
|
||||
dyn_i->dtpmod_offset = x->ofs;
|
||||
x->ofs += 8;
|
||||
}
|
||||
if (dyn_i->want_dtprel)
|
||||
{
|
||||
dyn_i->dtprel_offset = x->ofs;
|
||||
x->ofs += 8;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2582,6 +2681,10 @@ allocate_dynrel_entries (dyn_i, data)
|
||||
if (!dynamic_symbol)
|
||||
count *= 2;
|
||||
break;
|
||||
case R_IA64_TPREL64LSB:
|
||||
case R_IA64_DTPREL64LSB:
|
||||
case R_IA64_DTPMOD64LSB:
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
@ -2593,6 +2696,12 @@ allocate_dynrel_entries (dyn_i, data)
|
||||
if (((dynamic_symbol || shared) && dyn_i->want_got)
|
||||
|| (dyn_i->want_ltoff_fptr && dyn_i->h && dyn_i->h->dynindx != -1))
|
||||
ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
|
||||
if ((dynamic_symbol || shared) && dyn_i->want_tprel)
|
||||
ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
|
||||
if ((dynamic_symbol || shared) && dyn_i->want_dtpmod)
|
||||
ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
|
||||
if (dynamic_symbol && dyn_i->want_dtprel)
|
||||
ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
|
||||
|
||||
if (dyn_i->want_pltoff)
|
||||
{
|
||||
@ -2903,7 +3012,11 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
|
||||
|
||||
/* Instruction relocations. */
|
||||
|
||||
case R_IA64_IMM14: opnd = IA64_OPND_IMM14; break;
|
||||
case R_IA64_IMM14:
|
||||
case R_IA64_TPREL14:
|
||||
case R_IA64_DTPREL14:
|
||||
opnd = IA64_OPND_IMM14;
|
||||
break;
|
||||
|
||||
case R_IA64_PCREL21F: opnd = IA64_OPND_TGT25; break;
|
||||
case R_IA64_PCREL21M: opnd = IA64_OPND_TGT25b; break;
|
||||
@ -2920,6 +3033,11 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
|
||||
case R_IA64_PLTOFF22:
|
||||
case R_IA64_PCREL22:
|
||||
case R_IA64_LTOFF_FPTR22:
|
||||
case R_IA64_TPREL22:
|
||||
case R_IA64_DTPREL22:
|
||||
case R_IA64_LTOFF_TPREL22:
|
||||
case R_IA64_LTOFF_DTPMOD22:
|
||||
case R_IA64_LTOFF_DTPREL22:
|
||||
opnd = IA64_OPND_IMM22;
|
||||
break;
|
||||
|
||||
@ -2930,6 +3048,8 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
|
||||
case R_IA64_PCREL64I:
|
||||
case R_IA64_FPTR64I:
|
||||
case R_IA64_LTOFF_FPTR64I:
|
||||
case R_IA64_TPREL64I:
|
||||
case R_IA64_DTPREL64I:
|
||||
opnd = IA64_OPND_IMMU64;
|
||||
break;
|
||||
|
||||
@ -2943,6 +3063,7 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
|
||||
case R_IA64_SEGREL32MSB:
|
||||
case R_IA64_SECREL32MSB:
|
||||
case R_IA64_LTV32MSB:
|
||||
case R_IA64_DTPREL32MSB:
|
||||
size = 4; bigendian = 1;
|
||||
break;
|
||||
|
||||
@ -2954,6 +3075,7 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
|
||||
case R_IA64_SEGREL32LSB:
|
||||
case R_IA64_SECREL32LSB:
|
||||
case R_IA64_LTV32LSB:
|
||||
case R_IA64_DTPREL32LSB:
|
||||
size = 4; bigendian = 0;
|
||||
break;
|
||||
|
||||
@ -2966,6 +3088,9 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
|
||||
case R_IA64_SEGREL64MSB:
|
||||
case R_IA64_SECREL64MSB:
|
||||
case R_IA64_LTV64MSB:
|
||||
case R_IA64_TPREL64MSB:
|
||||
case R_IA64_DTPMOD64MSB:
|
||||
case R_IA64_DTPREL64MSB:
|
||||
size = 8; bigendian = 1;
|
||||
break;
|
||||
|
||||
@ -2978,6 +3103,9 @@ elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
|
||||
case R_IA64_SEGREL64LSB:
|
||||
case R_IA64_SECREL64LSB:
|
||||
case R_IA64_LTV64LSB:
|
||||
case R_IA64_TPREL64LSB:
|
||||
case R_IA64_DTPMOD64LSB:
|
||||
case R_IA64_DTPREL64LSB:
|
||||
size = 8; bigendian = 0;
|
||||
break;
|
||||
|
||||
@ -3132,26 +3260,53 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
|
||||
{
|
||||
struct elfNN_ia64_link_hash_table *ia64_info;
|
||||
asection *got_sec;
|
||||
boolean done;
|
||||
bfd_vma got_offset;
|
||||
|
||||
ia64_info = elfNN_ia64_hash_table (info);
|
||||
got_sec = ia64_info->got_sec;
|
||||
|
||||
BFD_ASSERT ((dyn_i->got_offset & 7) == 0);
|
||||
|
||||
if (! dyn_i->got_done)
|
||||
switch (dyn_r_type)
|
||||
{
|
||||
case R_IA64_TPREL64LSB:
|
||||
done = dyn_i->tprel_done;
|
||||
dyn_i->tprel_done = true;
|
||||
got_offset = dyn_i->tprel_offset;
|
||||
break;
|
||||
case R_IA64_DTPMOD64LSB:
|
||||
done = dyn_i->dtpmod_done;
|
||||
dyn_i->dtpmod_done = true;
|
||||
got_offset = dyn_i->dtpmod_offset;
|
||||
break;
|
||||
case R_IA64_DTPREL64LSB:
|
||||
done = dyn_i->dtprel_done;
|
||||
dyn_i->dtprel_done = true;
|
||||
got_offset = dyn_i->dtprel_offset;
|
||||
break;
|
||||
default:
|
||||
done = dyn_i->got_done;
|
||||
dyn_i->got_done = true;
|
||||
got_offset = dyn_i->got_offset;
|
||||
break;
|
||||
}
|
||||
|
||||
BFD_ASSERT ((got_offset & 7) == 0);
|
||||
|
||||
if (! done)
|
||||
{
|
||||
/* Store the target address in the linkage table entry. */
|
||||
bfd_put_64 (abfd, value, got_sec->contents + dyn_i->got_offset);
|
||||
bfd_put_64 (abfd, value, got_sec->contents + got_offset);
|
||||
|
||||
/* Install a dynamic relocation if needed. */
|
||||
if (info->shared
|
||||
if ((info->shared && dyn_r_type != R_IA64_DTPREL64LSB)
|
||||
|| elfNN_ia64_dynamic_symbol_p (dyn_i->h, info)
|
||||
|| elfNN_ia64_aix_vec (abfd->xvec)
|
||||
|| (dynindx != -1 && dyn_r_type == R_IA64_FPTR64LSB))
|
||||
{
|
||||
if (dynindx == -1)
|
||||
if (dynindx == -1
|
||||
&& dyn_r_type != R_IA64_TPREL64LSB
|
||||
&& dyn_r_type != R_IA64_DTPMOD64LSB
|
||||
&& dyn_r_type != R_IA64_DTPREL64LSB)
|
||||
{
|
||||
dyn_r_type = R_IA64_REL64LSB;
|
||||
dynindx = 0;
|
||||
@ -3171,6 +3326,15 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
|
||||
case R_IA64_FPTR64LSB:
|
||||
dyn_r_type = R_IA64_FPTR64MSB;
|
||||
break;
|
||||
case R_IA64_TPREL64LSB:
|
||||
dyn_r_type = R_IA64_TPREL64MSB;
|
||||
break;
|
||||
case R_IA64_DTPMOD64LSB:
|
||||
dyn_r_type = R_IA64_DTPMOD64MSB;
|
||||
break;
|
||||
case R_IA64_DTPREL64LSB:
|
||||
dyn_r_type = R_IA64_DTPREL64MSB;
|
||||
break;
|
||||
default:
|
||||
BFD_ASSERT (false);
|
||||
break;
|
||||
@ -3179,7 +3343,7 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
|
||||
|
||||
elfNN_ia64_install_dyn_reloc (abfd, NULL, got_sec,
|
||||
ia64_info->rel_got_sec,
|
||||
dyn_i->got_offset, dyn_r_type,
|
||||
got_offset, dyn_r_type,
|
||||
dynindx, addend);
|
||||
}
|
||||
}
|
||||
@ -3187,7 +3351,7 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
|
||||
/* Return the address of the linkage table entry. */
|
||||
value = (got_sec->output_section->vma
|
||||
+ got_sec->output_offset
|
||||
+ dyn_i->got_offset);
|
||||
+ got_offset);
|
||||
|
||||
return value;
|
||||
}
|
||||
@ -3285,6 +3449,35 @@ set_pltoff_entry (abfd, info, dyn_i, value, is_plt)
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Return the base VMA address which should be subtracted from real addresses
|
||||
when resolving @tprel() relocation.
|
||||
Main program TLS (whose template starts at PT_TLS p_vaddr)
|
||||
is assigned offset round(16, PT_TLS p_align). */
|
||||
|
||||
static bfd_vma
|
||||
elfNN_ia64_tprel_base (info)
|
||||
struct bfd_link_info *info;
|
||||
{
|
||||
struct elf_link_tls_segment *tls_segment
|
||||
= elf_hash_table (info)->tls_segment;
|
||||
|
||||
BFD_ASSERT (tls_segment != NULL);
|
||||
return (tls_segment->start
|
||||
- align_power ((bfd_vma) 16, tls_segment->align));
|
||||
}
|
||||
|
||||
/* Return the base VMA address which should be subtracted from real addresses
|
||||
when resolving @dtprel() relocation.
|
||||
This is PT_TLS segment p_vaddr. */
|
||||
|
||||
static bfd_vma
|
||||
elfNN_ia64_dtprel_base (info)
|
||||
struct bfd_link_info *info;
|
||||
{
|
||||
BFD_ASSERT (elf_hash_table (info)->tls_segment != NULL);
|
||||
return elf_hash_table (info)->tls_segment->start;
|
||||
}
|
||||
|
||||
/* Called through qsort to sort the .IA_64.unwind section during a
|
||||
non-relocatable link. Set elfNN_ia64_unwind_entry_compare_bfd
|
||||
to the output bfd so we can do proper endianness frobbing. */
|
||||
@ -4030,6 +4223,55 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
r_type);
|
||||
break;
|
||||
|
||||
case R_IA64_TPREL14:
|
||||
case R_IA64_TPREL22:
|
||||
case R_IA64_TPREL64I:
|
||||
value -= elfNN_ia64_tprel_base (info);
|
||||
r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
|
||||
break;
|
||||
|
||||
case R_IA64_DTPREL14:
|
||||
case R_IA64_DTPREL22:
|
||||
case R_IA64_DTPREL64I:
|
||||
value -= elfNN_ia64_dtprel_base (info);
|
||||
r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
|
||||
break;
|
||||
|
||||
case R_IA64_LTOFF_TPREL22:
|
||||
case R_IA64_LTOFF_DTPMOD22:
|
||||
case R_IA64_LTOFF_DTPREL22:
|
||||
{
|
||||
int got_r_type;
|
||||
|
||||
switch (r_type)
|
||||
{
|
||||
default:
|
||||
case R_IA64_LTOFF_TPREL22:
|
||||
if (!dynamic_symbol_p && !info->shared)
|
||||
value -= elfNN_ia64_tprel_base (info);
|
||||
got_r_type = R_IA64_TPREL64LSB;
|
||||
break;
|
||||
case R_IA64_LTOFF_DTPMOD22:
|
||||
if (!dynamic_symbol_p && !info->shared)
|
||||
value = 1;
|
||||
got_r_type = R_IA64_DTPMOD64LSB;
|
||||
break;
|
||||
case R_IA64_LTOFF_DTPREL22:
|
||||
if (!dynamic_symbol_p)
|
||||
value -= elfNN_ia64_dtprel_base (info);
|
||||
got_r_type = R_IA64_DTPREL64LSB;
|
||||
break;
|
||||
}
|
||||
dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, false);
|
||||
value = set_got_entry (input_bfd, info, dyn_i,
|
||||
(h ? h->dynindx : -1), rel->r_addend,
|
||||
value, got_r_type);
|
||||
value -= gp_val;
|
||||
r = elfNN_ia64_install_value (output_bfd, hit_addr, value,
|
||||
r_type);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
r = bfd_reloc_notsupported;
|
||||
break;
|
||||
|
30
bfd/libbfd.h
30
bfd/libbfd.h
@ -771,6 +771,15 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
|
||||
"BFD_RELOC_386_RELATIVE",
|
||||
"BFD_RELOC_386_GOTOFF",
|
||||
"BFD_RELOC_386_GOTPC",
|
||||
"BFD_RELOC_386_TLS_LE",
|
||||
"BFD_RELOC_386_TLS_GD",
|
||||
"BFD_RELOC_386_TLS_LDM",
|
||||
"BFD_RELOC_386_TLS_LDO_32",
|
||||
"BFD_RELOC_386_TLS_IE_32",
|
||||
"BFD_RELOC_386_TLS_LE_32",
|
||||
"BFD_RELOC_386_TLS_DTPMOD32",
|
||||
"BFD_RELOC_386_TLS_DTPOFF32",
|
||||
"BFD_RELOC_386_TLS_TPOFF32",
|
||||
"BFD_RELOC_X86_64_GOT32",
|
||||
"BFD_RELOC_X86_64_PLT32",
|
||||
"BFD_RELOC_X86_64_COPY",
|
||||
@ -1142,12 +1151,25 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
|
||||
"BFD_RELOC_IA64_IPLTMSB",
|
||||
"BFD_RELOC_IA64_IPLTLSB",
|
||||
"BFD_RELOC_IA64_COPY",
|
||||
"BFD_RELOC_IA64_TPREL22",
|
||||
"BFD_RELOC_IA64_TPREL64MSB",
|
||||
"BFD_RELOC_IA64_TPREL64LSB",
|
||||
"BFD_RELOC_IA64_LTOFF_TP22",
|
||||
"BFD_RELOC_IA64_LTOFF22X",
|
||||
"BFD_RELOC_IA64_LDXMOV",
|
||||
"BFD_RELOC_IA64_TPREL14",
|
||||
"BFD_RELOC_IA64_TPREL22",
|
||||
"BFD_RELOC_IA64_TPREL64I",
|
||||
"BFD_RELOC_IA64_TPREL64MSB",
|
||||
"BFD_RELOC_IA64_TPREL64LSB",
|
||||
"BFD_RELOC_IA64_LTOFF_TPREL22",
|
||||
"BFD_RELOC_IA64_DTPMOD64MSB",
|
||||
"BFD_RELOC_IA64_DTPMOD64LSB",
|
||||
"BFD_RELOC_IA64_LTOFF_DTPMOD22",
|
||||
"BFD_RELOC_IA64_DTPREL14",
|
||||
"BFD_RELOC_IA64_DTPREL22",
|
||||
"BFD_RELOC_IA64_DTPREL64I",
|
||||
"BFD_RELOC_IA64_DTPREL32MSB",
|
||||
"BFD_RELOC_IA64_DTPREL32LSB",
|
||||
"BFD_RELOC_IA64_DTPREL64MSB",
|
||||
"BFD_RELOC_IA64_DTPREL64LSB",
|
||||
"BFD_RELOC_IA64_LTOFF_DTPREL22",
|
||||
"BFD_RELOC_M68HC11_HI8",
|
||||
"BFD_RELOC_M68HC11_LO8",
|
||||
"BFD_RELOC_M68HC11_3B",
|
||||
|
50
bfd/reloc.c
50
bfd/reloc.c
@ -2072,6 +2072,24 @@ ENUMX
|
||||
BFD_RELOC_386_GOTOFF
|
||||
ENUMX
|
||||
BFD_RELOC_386_GOTPC
|
||||
ENUMX
|
||||
BFD_RELOC_386_TLS_LE
|
||||
ENUMX
|
||||
BFD_RELOC_386_TLS_GD
|
||||
ENUMX
|
||||
BFD_RELOC_386_TLS_LDM
|
||||
ENUMX
|
||||
BFD_RELOC_386_TLS_LDO_32
|
||||
ENUMX
|
||||
BFD_RELOC_386_TLS_IE_32
|
||||
ENUMX
|
||||
BFD_RELOC_386_TLS_LE_32
|
||||
ENUMX
|
||||
BFD_RELOC_386_TLS_DTPMOD32
|
||||
ENUMX
|
||||
BFD_RELOC_386_TLS_DTPOFF32
|
||||
ENUMX
|
||||
BFD_RELOC_386_TLS_TPOFF32
|
||||
ENUMDOC
|
||||
i386/elf relocations
|
||||
|
||||
@ -3184,18 +3202,44 @@ ENUMX
|
||||
BFD_RELOC_IA64_IPLTLSB
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_COPY
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_LTOFF22X
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_LDXMOV
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_TPREL14
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_TPREL22
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_TPREL64I
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_TPREL64MSB
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_TPREL64LSB
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_LTOFF_TP22
|
||||
BFD_RELOC_IA64_LTOFF_TPREL22
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_LTOFF22X
|
||||
BFD_RELOC_IA64_DTPMOD64MSB
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_LDXMOV
|
||||
BFD_RELOC_IA64_DTPMOD64LSB
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_LTOFF_DTPMOD22
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_DTPREL14
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_DTPREL22
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_DTPREL64I
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_DTPREL32MSB
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_DTPREL32LSB
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_DTPREL64MSB
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_DTPREL64LSB
|
||||
ENUMX
|
||||
BFD_RELOC_IA64_LTOFF_DTPREL22
|
||||
ENUMDOC
|
||||
Intel IA64 Relocations.
|
||||
|
||||
|
@ -230,12 +230,6 @@ CODE_FRAGMENT
|
||||
. standard data. *}
|
||||
.#define SEC_CONSTRUCTOR 0x100
|
||||
.
|
||||
. {* The section is a constructor, and should be placed at the
|
||||
. end of the text, data, or bss section(?). *}
|
||||
.#define SEC_CONSTRUCTOR_TEXT 0x1100
|
||||
.#define SEC_CONSTRUCTOR_DATA 0x2100
|
||||
.#define SEC_CONSTRUCTOR_BSS 0x3100
|
||||
.
|
||||
. {* The section has contents - a data section could be
|
||||
. <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>; a debug section could be
|
||||
. <<SEC_HAS_CONTENTS>> *}
|
||||
@ -256,6 +250,9 @@ CODE_FRAGMENT
|
||||
. sections. *}
|
||||
.#define SEC_COFF_SHARED_LIBRARY 0x800
|
||||
.
|
||||
. {* The section contains thread local data. *}
|
||||
.#define SEC_THREAD_LOCAL 0x1000
|
||||
.
|
||||
. {* The section has GOT references. This flag is only for the
|
||||
. linker, and is currently only used by the elf32-hppa back end.
|
||||
. It will be set if global offset table references were detected
|
||||
|
@ -285,6 +285,9 @@ CODE_FRAGMENT
|
||||
. as well. *}
|
||||
.#define BSF_DEBUGGING_RELOC 0x20000
|
||||
.
|
||||
. {* This symbol is thread local. Used in ELF. *}
|
||||
.#define BSF_THREAD_LOCAL 0x40000
|
||||
.
|
||||
. flagword flags;
|
||||
.
|
||||
. {* A pointer to the section to which this symbol is
|
||||
|
@ -1,3 +1,14 @@
|
||||
2002-05-23 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* readelf.c (get_segment_type): Add PT_TLS.
|
||||
(get_elf_section_flags): Add SHF_TLS.
|
||||
(get_dynamic_flags): Optimize. Add DF_STATIC_TLS.
|
||||
(process_dynamic_segment): Use puts instead of printf.
|
||||
(get_symbol_type): Support STT_TLS.
|
||||
* objdump.c (dump_section_header): Remove SEC_CONSTRUCTOR_TEXT,
|
||||
SEC_CONSTRUCTOR_DATA, SEC_CONSTRUCTOR_BSS.
|
||||
Add SEC_THREAD_LOCAL.
|
||||
|
||||
2002-05-23 Kazu Hirata <kazu@cs.umass.edu>
|
||||
|
||||
* rdcoff.c: Fix formatting.
|
||||
|
@ -299,9 +299,6 @@ dump_section_header (abfd, section, ignored)
|
||||
PF (SEC_HAS_CONTENTS, "CONTENTS");
|
||||
PF (SEC_ALLOC, "ALLOC");
|
||||
PF (SEC_CONSTRUCTOR, "CONSTRUCTOR");
|
||||
PF (SEC_CONSTRUCTOR_TEXT, "CONSTRUCTOR TEXT");
|
||||
PF (SEC_CONSTRUCTOR_DATA, "CONSTRUCTOR DATA");
|
||||
PF (SEC_CONSTRUCTOR_BSS, "CONSTRUCTOR BSS");
|
||||
PF (SEC_LOAD, "LOAD");
|
||||
PF (SEC_RELOC, "RELOC");
|
||||
PF (SEC_READONLY, "READONLY");
|
||||
@ -317,6 +314,7 @@ dump_section_header (abfd, section, ignored)
|
||||
PF (SEC_SMALL_DATA, "SMALL_DATA");
|
||||
PF (SEC_SHARED, "SHARED");
|
||||
PF (SEC_ARCH_BIT_0, "ARCH_BIT_0");
|
||||
PF (SEC_THREAD_LOCAL, "THREAD_LOCAL");
|
||||
|
||||
if ((section->flags & SEC_LINK_ONCE) != 0)
|
||||
{
|
||||
|
@ -1987,6 +1987,7 @@ get_segment_type (p_type)
|
||||
case PT_NOTE: return "NOTE";
|
||||
case PT_SHLIB: return "SHLIB";
|
||||
case PT_PHDR: return "PHDR";
|
||||
case PT_TLS: return "TLS";
|
||||
|
||||
case PT_GNU_EH_FRAME:
|
||||
return "GNU_EH_FRAME";
|
||||
@ -3202,6 +3203,7 @@ get_elf_section_flags (sh_flags)
|
||||
case SHF_LINK_ORDER: strcat (buff, "L"); break;
|
||||
case SHF_OS_NONCONFORMING: strcat (buff, "O"); break;
|
||||
case SHF_GROUP: strcat (buff, "G"); break;
|
||||
case SHF_TLS: strcat (buff, "T"); break;
|
||||
|
||||
default:
|
||||
if (flag & SHF_MASKOS)
|
||||
@ -4242,7 +4244,10 @@ static const char *
|
||||
get_dynamic_flags (flags)
|
||||
bfd_vma flags;
|
||||
{
|
||||
static char buff [64];
|
||||
static char buff [128];
|
||||
char *p = buff;
|
||||
|
||||
*p = '\0';
|
||||
while (flags)
|
||||
{
|
||||
bfd_vma flag;
|
||||
@ -4250,14 +4255,20 @@ get_dynamic_flags (flags)
|
||||
flag = flags & - flags;
|
||||
flags &= ~ flag;
|
||||
|
||||
if (p != buff)
|
||||
*p++ = ' ';
|
||||
|
||||
switch (flag)
|
||||
{
|
||||
case DF_ORIGIN: strcat (buff, "ORIGIN "); break;
|
||||
case DF_SYMBOLIC: strcat (buff, "SYMBOLIC "); break;
|
||||
case DF_TEXTREL: strcat (buff, "TEXTREL "); break;
|
||||
case DF_BIND_NOW: strcat (buff, "BIND_NOW "); break;
|
||||
default: strcat (buff, "unknown "); break;
|
||||
case DF_ORIGIN: strcpy (p, "ORIGIN"); break;
|
||||
case DF_SYMBOLIC: strcpy (p, "SYMBOLIC"); break;
|
||||
case DF_TEXTREL: strcpy (p, "TEXTREL"); break;
|
||||
case DF_BIND_NOW: strcpy (p, "BIND_NOW"); break;
|
||||
case DF_STATIC_TLS: strcpy (p, "STATIC_TLS"); break;
|
||||
default: strcpy (p, "unknown"); break;
|
||||
}
|
||||
|
||||
p = strchr (p, '\0');
|
||||
}
|
||||
return buff;
|
||||
}
|
||||
@ -4443,7 +4454,7 @@ process_dynamic_segment (file)
|
||||
{
|
||||
case DT_FLAGS:
|
||||
if (do_dynamic)
|
||||
printf ("%s", get_dynamic_flags (entry->d_un.d_val));
|
||||
puts (get_dynamic_flags (entry->d_un.d_val));
|
||||
break;
|
||||
|
||||
case DT_AUXILIARY:
|
||||
@ -5252,6 +5263,7 @@ get_symbol_type (type)
|
||||
case STT_SECTION: return "SECTION";
|
||||
case STT_FILE: return "FILE";
|
||||
case STT_COMMON: return "COMMON";
|
||||
case STT_TLS: return "TLS";
|
||||
default:
|
||||
if (type >= STT_LOPROC && type <= STT_HIPROC)
|
||||
{
|
||||
|
@ -1,3 +1,45 @@
|
||||
2002-05-23 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* config/obj-elf.c (elf_common): Renamed from obj_elf_common.
|
||||
(obj_elf_common): Call elf_common.
|
||||
(obj_elf_tls_common): New function.
|
||||
(elf_pseudo_tab): Support .tls_common.
|
||||
(special_sections): Add .tdata and .tbss.
|
||||
(obj_elf_change_section): Set SEC_THREAD_LOCAL for SHF_TLS
|
||||
sections.
|
||||
(obj_elf_parse_section_letters): Support T in section flags (SHF_TLS).
|
||||
(obj_elf_parse_section_letters): Include T in error message.
|
||||
* config/tc-ppc.c (ppc_section_letter): Likewise.
|
||||
* config/tc-alpha.c (alpha_elf_section_letter): Likewise.
|
||||
(tc_gen_reloc): Handle SEC_THREAD_LOCAL the same way as
|
||||
SEC_MERGE.
|
||||
* config/tc-sparc.c (md_apply_fix3): Likewise.
|
||||
* config/tc-i386.c (tc_i386_fix_adjustable): Add TLS relocs.
|
||||
Define them if not BFD_ASSEMBLER.
|
||||
(lex_got): Support @TLSGD, @TLSLDM, @GOTTPOFF, @TPOFF, @DTPOFF
|
||||
and @NTPOFF.
|
||||
(md_apply_fix3): Add TLS relocs.
|
||||
* config/tc-ia64.c (enum reloc_func): Add FUNC_DTP_MODULE,
|
||||
FUNC_DTP_RELATIVE, FUNC_TP_RELATIVE, FUNC_LT_DTP_MODULE,
|
||||
FUNC_LT_DTP_RELATIVE, FUNC_LT_TP_RELATIVE.
|
||||
(pseudo_func): Support @dtpmod(), @dtprel() and @tprel().
|
||||
(ia64_elf_section_letter): Include T in error message.
|
||||
(md_begin): Support TLS operators.
|
||||
(md_operand): Likewise.
|
||||
(ia64_gen_real_reloc_type): Support TLS relocs.
|
||||
* testsuite/gas/i386/tlspic.s: New file.
|
||||
* testsuite/gas/i386/tlsd.s: New file.
|
||||
* testsuite/gas/i386/tlsnopic.s: New file.
|
||||
* testsuite/gas/i386/tlsd.d: New file.
|
||||
* testsuite/gas/i386/tlsnopic.d: New file.
|
||||
* testsuite/gas/i386/tlspic.d: New file.
|
||||
* testsuite/gas/i386/i386.exp: Add tlsd, tlsnopic and tlspic tests.
|
||||
* testsuite/gas/ia64/tls.s: New file.
|
||||
* testsuite/gas/ia64/tls.d: New file.
|
||||
* testsuite/gas/ia64/ia64.exp: Add tls test.
|
||||
* write.c (adjust_reloc_syms): Don't change symbols in
|
||||
SEC_THREAD_LOCAL sections to STT_SECTION + addend.
|
||||
|
||||
2002-05-23 Nick Clifton <nickc@cambridge.redhat.com>
|
||||
|
||||
* config/tc-arm.c (md_apply_fix3): For the Thumb BLX reloc
|
||||
|
@ -61,6 +61,7 @@ static void adjust_stab_sections PARAMS ((bfd *, asection *, PTR));
|
||||
static void build_group_lists PARAMS ((bfd *, asection *, PTR));
|
||||
static int elf_separate_stab_sections PARAMS ((void));
|
||||
static void elf_init_stab_section PARAMS ((segT));
|
||||
static symbolS *elf_common PARAMS ((int));
|
||||
|
||||
#ifdef NEED_ECOFF_DEBUG
|
||||
static boolean elf_get_extr PARAMS ((asymbol *, EXTR *));
|
||||
@ -84,6 +85,7 @@ static int obj_elf_section_type PARAMS ((char *, size_t));
|
||||
static void obj_elf_symver PARAMS ((int));
|
||||
static void obj_elf_subsection PARAMS ((int));
|
||||
static void obj_elf_popsection PARAMS ((int));
|
||||
static void obj_elf_tls_common PARAMS ((int));
|
||||
|
||||
static const pseudo_typeS elf_pseudo_table[] =
|
||||
{
|
||||
@ -130,6 +132,8 @@ static const pseudo_typeS elf_pseudo_table[] =
|
||||
{"data", obj_elf_data, 0},
|
||||
{"text", obj_elf_text, 0},
|
||||
|
||||
{"tls_common", obj_elf_tls_common, 0},
|
||||
|
||||
/* End sentinel. */
|
||||
{NULL, NULL, 0},
|
||||
};
|
||||
@ -280,8 +284,8 @@ elf_file_symbol (s)
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
obj_elf_common (is_common)
|
||||
static symbolS *
|
||||
elf_common (is_common)
|
||||
int is_common;
|
||||
{
|
||||
char *name;
|
||||
@ -294,7 +298,7 @@ obj_elf_common (is_common)
|
||||
if (flag_mri && is_common)
|
||||
{
|
||||
s_mri_common (0);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
name = input_line_pointer;
|
||||
@ -307,14 +311,14 @@ obj_elf_common (is_common)
|
||||
{
|
||||
as_bad (_("expected comma after symbol-name"));
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
input_line_pointer++; /* skip ',' */
|
||||
if ((temp = get_absolute_expression ()) < 0)
|
||||
{
|
||||
as_bad (_(".COMMon length (%d.) <0! Ignored."), temp);
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
size = temp;
|
||||
*p = 0;
|
||||
@ -324,7 +328,7 @@ obj_elf_common (is_common)
|
||||
{
|
||||
as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
if (S_GET_VALUE (symbolP) != 0)
|
||||
{
|
||||
@ -374,7 +378,7 @@ obj_elf_common (is_common)
|
||||
{
|
||||
as_bad (_("common alignment not a power of 2"));
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -426,7 +430,7 @@ obj_elf_common (is_common)
|
||||
symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
return;
|
||||
return symbolP;
|
||||
|
||||
{
|
||||
bad_common_segment:
|
||||
@ -439,10 +443,27 @@ obj_elf_common (is_common)
|
||||
*p = c;
|
||||
input_line_pointer = p;
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
obj_elf_common (is_common)
|
||||
int is_common;
|
||||
{
|
||||
elf_common (is_common);
|
||||
}
|
||||
|
||||
static void
|
||||
obj_elf_tls_common (ignore)
|
||||
int ignore ATTRIBUTE_UNUSED;
|
||||
{
|
||||
symbolS *symbolP = elf_common (0);
|
||||
|
||||
if (symbolP)
|
||||
symbol_get_bfdsym (symbolP)->flags |= BSF_THREAD_LOCAL;
|
||||
}
|
||||
|
||||
static void
|
||||
obj_elf_local (ignore)
|
||||
int ignore ATTRIBUTE_UNUSED;
|
||||
@ -594,6 +615,8 @@ static struct special_section const special_sections[] =
|
||||
{ ".note", SHT_NOTE, 0 },
|
||||
{ ".rodata", SHT_PROGBITS, SHF_ALLOC },
|
||||
{ ".rodata1", SHT_PROGBITS, SHF_ALLOC },
|
||||
{ ".tbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_TLS },
|
||||
{ ".tdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_TLS },
|
||||
{ ".text", SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
|
||||
#if 0
|
||||
/* FIXME: The current gcc, as of 2002-03-03, will emit
|
||||
@ -717,7 +740,8 @@ obj_elf_change_section (name, type, attr, entsize, group_name, push)
|
||||
| (((attr & SHF_ALLOC) && type != SHT_NOBITS) ? SEC_LOAD : 0)
|
||||
| ((attr & SHF_EXECINSTR) ? SEC_CODE : 0)
|
||||
| ((attr & SHF_MERGE) ? SEC_MERGE : 0)
|
||||
| ((attr & SHF_STRINGS) ? SEC_STRINGS : 0));
|
||||
| ((attr & SHF_STRINGS) ? SEC_STRINGS : 0)
|
||||
| ((attr & SHF_TLS) ? SEC_THREAD_LOCAL : 0));
|
||||
#ifdef md_elf_section_flags
|
||||
flags = md_elf_section_flags (flags, attr, type);
|
||||
#endif
|
||||
@ -749,7 +773,8 @@ obj_elf_change_section (name, type, attr, entsize, group_name, push)
|
||||
saw the first time. */
|
||||
if ((old_sec->flags ^ flags)
|
||||
& (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
|
||||
| SEC_EXCLUDE | SEC_SORT_ENTRIES | SEC_MERGE | SEC_STRINGS))
|
||||
| SEC_EXCLUDE | SEC_SORT_ENTRIES | SEC_MERGE | SEC_STRINGS
|
||||
| SEC_THREAD_LOCAL))
|
||||
as_warn (_("ignoring changed section attributes for %s"), name);
|
||||
else if ((flags & SEC_MERGE) && old_sec->entsize != (unsigned) entsize)
|
||||
as_warn (_("ignoring changed section entity size for %s"), name);
|
||||
@ -792,6 +817,9 @@ obj_elf_parse_section_letters (str, len)
|
||||
case 'G':
|
||||
attr |= SHF_GROUP;
|
||||
break;
|
||||
case 'T':
|
||||
attr |= SHF_TLS;
|
||||
break;
|
||||
/* Compatibility. */
|
||||
case 'm':
|
||||
if (*(str - 1) == 'a')
|
||||
@ -806,7 +834,7 @@ obj_elf_parse_section_letters (str, len)
|
||||
}
|
||||
default:
|
||||
{
|
||||
char *bad_msg = _("unrecognized .section attribute: want a,w,x,M,S,G");
|
||||
char *bad_msg = _("unrecognized .section attribute: want a,w,x,M,S,G,T");
|
||||
#ifdef md_elf_section_letter
|
||||
int md_attr = md_elf_section_letter (*str, &bad_msg);
|
||||
if (md_attr >= 0)
|
||||
|
@ -1556,7 +1556,8 @@ tc_gen_reloc (sec, fixp)
|
||||
* of thing, and as a result we need to fake it out here.
|
||||
*/
|
||||
if ((S_IS_EXTERN (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy)
|
||||
|| (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE))
|
||||
|| (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE)
|
||||
|| (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_THREAD_LOCAL))
|
||||
&& !S_IS_COMMON (fixp->fx_addsy))
|
||||
reloc->addend -= symbol_get_bfdsym (fixp->fx_addsy)->value;
|
||||
#endif
|
||||
@ -5467,7 +5468,7 @@ alpha_elf_section_letter (letter, ptr_msg)
|
||||
if (letter == 's')
|
||||
return SHF_ALPHA_GPREL;
|
||||
|
||||
*ptr_msg = _("Bad .section directive: want a,s,w,x,M,S in string");
|
||||
*ptr_msg = _("Bad .section directive: want a,s,w,x,M,S,G,T in string");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1219,6 +1219,12 @@ tc_i386_fix_adjustable (fixP)
|
||||
if (fixP->fx_r_type == BFD_RELOC_386_GOTOFF
|
||||
|| fixP->fx_r_type == BFD_RELOC_386_PLT32
|
||||
|| fixP->fx_r_type == BFD_RELOC_386_GOT32
|
||||
|| fixP->fx_r_type == BFD_RELOC_386_TLS_GD
|
||||
|| fixP->fx_r_type == BFD_RELOC_386_TLS_LDM
|
||||
|| fixP->fx_r_type == BFD_RELOC_386_TLS_LDO_32
|
||||
|| fixP->fx_r_type == BFD_RELOC_386_TLS_IE_32
|
||||
|| fixP->fx_r_type == BFD_RELOC_386_TLS_LE_32
|
||||
|| fixP->fx_r_type == BFD_RELOC_386_TLS_LE
|
||||
|| fixP->fx_r_type == BFD_RELOC_X86_64_PLT32
|
||||
|| fixP->fx_r_type == BFD_RELOC_X86_64_GOT32
|
||||
|| fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCREL
|
||||
@ -1236,6 +1242,12 @@ tc_i386_fix_adjustable (fixP)
|
||||
#define BFD_RELOC_386_PLT32 0
|
||||
#define BFD_RELOC_386_GOT32 0
|
||||
#define BFD_RELOC_386_GOTOFF 0
|
||||
#define BFD_RELOC_386_TLS_GD 0
|
||||
#define BFD_RELOC_386_TLS_LDM 0
|
||||
#define BFD_RELOC_386_TLS_LDO_32 0
|
||||
#define BFD_RELOC_386_TLS_IE_32 0
|
||||
#define BFD_RELOC_386_TLS_LE_32 0
|
||||
#define BFD_RELOC_386_TLS_LE 0
|
||||
#define BFD_RELOC_X86_64_PLT32 0
|
||||
#define BFD_RELOC_X86_64_GOT32 0
|
||||
#define BFD_RELOC_X86_64_GOTPCREL 0
|
||||
@ -3374,6 +3386,12 @@ lex_got (reloc, adjust)
|
||||
{ "PLT", { BFD_RELOC_386_PLT32, 0, BFD_RELOC_X86_64_PLT32 } },
|
||||
{ "GOTOFF", { BFD_RELOC_386_GOTOFF, 0, 0 } },
|
||||
{ "GOTPCREL", { 0, 0, BFD_RELOC_X86_64_GOTPCREL } },
|
||||
{ "TLSGD", { BFD_RELOC_386_TLS_GD, 0, 0 } },
|
||||
{ "TLSLDM", { BFD_RELOC_386_TLS_LDM, 0, 0 } },
|
||||
{ "GOTTPOFF", { BFD_RELOC_386_TLS_IE_32, 0, 0 } },
|
||||
{ "TPOFF", { BFD_RELOC_386_TLS_LE_32, 0, 0 } },
|
||||
{ "NTPOFF", { BFD_RELOC_386_TLS_LE, 0, 0 } },
|
||||
{ "DTPOFF", { BFD_RELOC_386_TLS_LDO_32, 0, 0 } },
|
||||
{ "GOT", { BFD_RELOC_386_GOT32, 0, BFD_RELOC_X86_64_GOT32 } }
|
||||
};
|
||||
char *cp;
|
||||
@ -4577,6 +4595,12 @@ md_apply_fix3 (fixP, valP, seg)
|
||||
value -= 1;
|
||||
break;
|
||||
case BFD_RELOC_386_GOT32:
|
||||
case BFD_RELOC_386_TLS_GD:
|
||||
case BFD_RELOC_386_TLS_LDM:
|
||||
case BFD_RELOC_386_TLS_LDO_32:
|
||||
case BFD_RELOC_386_TLS_IE_32:
|
||||
case BFD_RELOC_386_TLS_LE_32:
|
||||
case BFD_RELOC_386_TLS_LE:
|
||||
case BFD_RELOC_X86_64_GOT32:
|
||||
value = 0; /* Fully resolved at runtime. No addend. */
|
||||
break;
|
||||
@ -5045,6 +5069,12 @@ tc_gen_reloc (section, fixp)
|
||||
case BFD_RELOC_386_GOT32:
|
||||
case BFD_RELOC_386_GOTOFF:
|
||||
case BFD_RELOC_386_GOTPC:
|
||||
case BFD_RELOC_386_TLS_GD:
|
||||
case BFD_RELOC_386_TLS_LDM:
|
||||
case BFD_RELOC_386_TLS_LDO_32:
|
||||
case BFD_RELOC_386_TLS_IE_32:
|
||||
case BFD_RELOC_386_TLS_LE_32:
|
||||
case BFD_RELOC_386_TLS_LE:
|
||||
case BFD_RELOC_X86_64_32S:
|
||||
case BFD_RELOC_RVA:
|
||||
case BFD_RELOC_VTABLE_ENTRY:
|
||||
|
@ -77,6 +77,8 @@ enum special_section
|
||||
|
||||
enum reloc_func
|
||||
{
|
||||
FUNC_DTP_MODULE,
|
||||
FUNC_DTP_RELATIVE,
|
||||
FUNC_FPTR_RELATIVE,
|
||||
FUNC_GP_RELATIVE,
|
||||
FUNC_LT_RELATIVE,
|
||||
@ -84,8 +86,12 @@ enum reloc_func
|
||||
FUNC_PLT_RELATIVE,
|
||||
FUNC_SEC_RELATIVE,
|
||||
FUNC_SEG_RELATIVE,
|
||||
FUNC_TP_RELATIVE,
|
||||
FUNC_LTV_RELATIVE,
|
||||
FUNC_LT_FPTR_RELATIVE,
|
||||
FUNC_LT_DTP_MODULE,
|
||||
FUNC_LT_DTP_RELATIVE,
|
||||
FUNC_LT_TP_RELATIVE,
|
||||
FUNC_IPLT_RELOC,
|
||||
};
|
||||
|
||||
@ -476,6 +482,8 @@ static struct
|
||||
pseudo_func[] =
|
||||
{
|
||||
/* reloc pseudo functions (these must come first!): */
|
||||
{ "dtpmod", PSEUDO_FUNC_RELOC, { 0 } },
|
||||
{ "dtprel", PSEUDO_FUNC_RELOC, { 0 } },
|
||||
{ "fptr", PSEUDO_FUNC_RELOC, { 0 } },
|
||||
{ "gprel", PSEUDO_FUNC_RELOC, { 0 } },
|
||||
{ "ltoff", PSEUDO_FUNC_RELOC, { 0 } },
|
||||
@ -483,8 +491,12 @@ pseudo_func[] =
|
||||
{ "pltoff", PSEUDO_FUNC_RELOC, { 0 } },
|
||||
{ "secrel", PSEUDO_FUNC_RELOC, { 0 } },
|
||||
{ "segrel", PSEUDO_FUNC_RELOC, { 0 } },
|
||||
{ "tprel", PSEUDO_FUNC_RELOC, { 0 } },
|
||||
{ "ltv", PSEUDO_FUNC_RELOC, { 0 } },
|
||||
{ "", 0, { 0 } }, /* placeholder for FUNC_LT_FPTR_RELATIVE */
|
||||
{ "", 0, { 0 } }, /* placeholder for FUNC_LT_DTP_MODULE */
|
||||
{ "", 0, { 0 } }, /* placeholder for FUNC_LT_DTP_RELATIVE */
|
||||
{ "", 0, { 0 } }, /* placeholder for FUNC_LT_TP_RELATIVE */
|
||||
{ "iplt", PSEUDO_FUNC_RELOC, { 0 } },
|
||||
|
||||
/* mbtype4 constants: */
|
||||
@ -943,7 +955,7 @@ ia64_elf_section_letter (letter, ptr_msg)
|
||||
if (letter == 's')
|
||||
return SHF_IA_64_SHORT;
|
||||
|
||||
*ptr_msg = _("Bad .section directive: want a,s,w,x,M,S in string");
|
||||
*ptr_msg = _("Bad .section directive: want a,s,w,x,M,S,G,T in string");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -6494,6 +6506,14 @@ md_begin ()
|
||||
bfd_set_section_alignment (stdoutput, text_section, 4);
|
||||
|
||||
target_big_endian = TARGET_BYTES_BIG_ENDIAN;
|
||||
pseudo_func[FUNC_DTP_MODULE].u.sym =
|
||||
symbol_new (".<dtpmod>", undefined_section, FUNC_DTP_MODULE,
|
||||
&zero_address_frag);
|
||||
|
||||
pseudo_func[FUNC_DTP_RELATIVE].u.sym =
|
||||
symbol_new (".<dtprel>", undefined_section, FUNC_DTP_RELATIVE,
|
||||
&zero_address_frag);
|
||||
|
||||
pseudo_func[FUNC_FPTR_RELATIVE].u.sym =
|
||||
symbol_new (".<fptr>", undefined_section, FUNC_FPTR_RELATIVE,
|
||||
&zero_address_frag);
|
||||
@ -6522,6 +6542,10 @@ md_begin ()
|
||||
symbol_new (".<segrel>", undefined_section, FUNC_SEG_RELATIVE,
|
||||
&zero_address_frag);
|
||||
|
||||
pseudo_func[FUNC_TP_RELATIVE].u.sym =
|
||||
symbol_new (".<tprel>", undefined_section, FUNC_TP_RELATIVE,
|
||||
&zero_address_frag);
|
||||
|
||||
pseudo_func[FUNC_LTV_RELATIVE].u.sym =
|
||||
symbol_new (".<ltv>", undefined_section, FUNC_LTV_RELATIVE,
|
||||
&zero_address_frag);
|
||||
@ -6530,6 +6554,18 @@ md_begin ()
|
||||
symbol_new (".<ltoff.fptr>", undefined_section, FUNC_LT_FPTR_RELATIVE,
|
||||
&zero_address_frag);
|
||||
|
||||
pseudo_func[FUNC_LT_DTP_MODULE].u.sym =
|
||||
symbol_new (".<ltoff.dtpmod>", undefined_section, FUNC_LT_DTP_MODULE,
|
||||
&zero_address_frag);
|
||||
|
||||
pseudo_func[FUNC_LT_DTP_RELATIVE].u.sym =
|
||||
symbol_new (".<ltoff.dptrel>", undefined_section, FUNC_LT_DTP_RELATIVE,
|
||||
&zero_address_frag);
|
||||
|
||||
pseudo_func[FUNC_LT_TP_RELATIVE].u.sym =
|
||||
symbol_new (".<ltoff.tprel>", undefined_section, FUNC_LT_TP_RELATIVE,
|
||||
&zero_address_frag);
|
||||
|
||||
pseudo_func[FUNC_IPLT_RELOC].u.sym =
|
||||
symbol_new (".<iplt>", undefined_section, FUNC_IPLT_RELOC,
|
||||
&zero_address_frag);
|
||||
@ -9826,14 +9862,25 @@ md_operand (e)
|
||||
as_bad ("Not a symbolic expression");
|
||||
goto err;
|
||||
}
|
||||
if (S_GET_VALUE (e->X_op_symbol) == FUNC_FPTR_RELATIVE
|
||||
&& i == FUNC_LT_RELATIVE)
|
||||
i = FUNC_LT_FPTR_RELATIVE;
|
||||
else
|
||||
if (i != FUNC_LT_RELATIVE)
|
||||
{
|
||||
as_bad ("Illegal combination of relocation functions");
|
||||
goto err;
|
||||
}
|
||||
switch (S_GET_VALUE (e->X_op_symbol))
|
||||
{
|
||||
case FUNC_FPTR_RELATIVE:
|
||||
i = FUNC_LT_FPTR_RELATIVE; break;
|
||||
case FUNC_DTP_MODULE:
|
||||
i = FUNC_LT_DTP_MODULE; break;
|
||||
case FUNC_DTP_RELATIVE:
|
||||
i = FUNC_LT_DTP_RELATIVE; break;
|
||||
case FUNC_TP_RELATIVE:
|
||||
i = FUNC_LT_TP_RELATIVE; break;
|
||||
default:
|
||||
as_bad ("Illegal combination of relocation functions");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
/* Make sure gas doesn't get rid of local symbols that are used
|
||||
in relocs. */
|
||||
@ -10163,6 +10210,64 @@ ia64_gen_real_reloc_type (sym, r_type)
|
||||
}
|
||||
break;
|
||||
|
||||
case FUNC_TP_RELATIVE:
|
||||
switch (r_type)
|
||||
{
|
||||
case BFD_RELOC_IA64_IMM14:
|
||||
new = BFD_RELOC_IA64_TPREL14; break;
|
||||
case BFD_RELOC_IA64_IMM22:
|
||||
new = BFD_RELOC_IA64_TPREL22; break;
|
||||
case BFD_RELOC_IA64_IMM64:
|
||||
new = BFD_RELOC_IA64_TPREL64I; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FUNC_LT_TP_RELATIVE:
|
||||
switch (r_type)
|
||||
{
|
||||
case BFD_RELOC_IA64_IMM22:
|
||||
new = BFD_RELOC_IA64_LTOFF_TPREL22; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FUNC_LT_DTP_MODULE:
|
||||
switch (r_type)
|
||||
{
|
||||
case BFD_RELOC_IA64_IMM22:
|
||||
new = BFD_RELOC_IA64_LTOFF_DTPMOD22; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FUNC_DTP_RELATIVE:
|
||||
switch (r_type)
|
||||
{
|
||||
case BFD_RELOC_IA64_IMM14:
|
||||
new = BFD_RELOC_IA64_DTPREL14; break;
|
||||
case BFD_RELOC_IA64_IMM22:
|
||||
new = BFD_RELOC_IA64_DTPREL22; break;
|
||||
case BFD_RELOC_IA64_IMM64:
|
||||
new = BFD_RELOC_IA64_DTPREL64I; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FUNC_LT_DTP_RELATIVE:
|
||||
switch (r_type)
|
||||
{
|
||||
case BFD_RELOC_IA64_IMM22:
|
||||
new = BFD_RELOC_IA64_LTOFF_DTPREL22; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FUNC_IPLT_RELOC:
|
||||
break;
|
||||
|
||||
|
@ -2485,7 +2485,7 @@ ppc_section_letter (letter, ptr_msg)
|
||||
if (letter == 'e')
|
||||
return SHF_EXCLUDE;
|
||||
|
||||
*ptr_msg = _("Bad .section directive: want a,e,w,x,M,S in string");
|
||||
*ptr_msg = _("Bad .section directive: want a,e,w,x,M,S,G,T in string");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2916,6 +2916,7 @@ md_apply_fix3 (fixP, valP, segment)
|
||||
&& (S_IS_EXTERNAL (sym)
|
||||
|| S_IS_WEAK (sym)
|
||||
|| (seg->flags & SEC_MERGE)
|
||||
|| (seg->flags & SEC_THREAD_LOCAL)
|
||||
|| (sparc_pic_code && ! fixP->fx_pcrel)
|
||||
|| (seg != segment
|
||||
&& (((bfd_get_section_flags (stdoutput, seg) & SEC_LINK_ONCE) != 0)
|
||||
|
@ -75,6 +75,9 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_32_check]]
|
||||
&& ![istarget *-*-linux*oldld*])
|
||||
} then {
|
||||
run_dump_test "relax"
|
||||
run_dump_test "tlsd"
|
||||
run_dump_test "tlspic"
|
||||
run_dump_test "tlsnopic"
|
||||
}
|
||||
|
||||
set ASFLAGS "$old_ASFLAGS"
|
||||
|
33
gas/testsuite/gas/i386/tlsd.d
Normal file
33
gas/testsuite/gas/i386/tlsd.d
Normal file
@ -0,0 +1,33 @@
|
||||
#objdump: -dr
|
||||
#name: i386 dynamic tls
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
0+000 <fn>:
|
||||
0: 55 [ ]*push %ebp
|
||||
1: 89 e5 [ ]*mov %esp,%ebp
|
||||
3: 53 [ ]*push %ebx
|
||||
4: 50 [ ]*push %eax
|
||||
5: e8 00 00 00 00 [ ]*call a <fn\+0xa>
|
||||
a: 5b [ ]*pop %ebx
|
||||
b: 81 c3 03 00 00 00 [ ]*add \$0x3,%ebx
|
||||
[ ]+d: R_386_GOTPC _GLOBAL_OFFSET_TABLE_
|
||||
11: 8d 04 1d 00 00 00 00 [ ]*lea 0x0\(,%ebx,1\),%eax
|
||||
[ ]+14: R_386_TLS_GD foo
|
||||
18: e8 fc ff ff ff [ ]*call 19 <fn\+0x19>
|
||||
[ ]+19: R_386_PLT32 ___tls_get_addr
|
||||
1d: 8d 83 00 00 00 00 [ ]*lea 0x0\(%ebx\),%eax
|
||||
[ ]+1f: R_386_TLS_LDM bar
|
||||
23: e8 fc ff ff ff [ ]*call 24 <fn\+0x24>
|
||||
[ ]+24: R_386_PLT32 ___tls_get_addr
|
||||
28: 8d 7f 00 [ ]*lea 0x0\(%edi\),%edi
|
||||
2b: 8d 90 00 00 00 00 [ ]*lea 0x0\(%eax\),%edx
|
||||
[ ]+2d: R_386_TLS_LDO_32 bar
|
||||
31: 8d 76 00 [ ]*lea 0x0\(%esi\),%esi
|
||||
34: 8d 88 00 00 00 00 [ ]*lea 0x0\(%eax\),%ecx
|
||||
[ ]+36: R_386_TLS_LDO_32 baz
|
||||
3a: 8b 5d fc [ ]*mov 0xfffffffc\(%ebp\),%ebx
|
||||
3d: c9 [ ]*leave[ ]*
|
||||
3e: c3 [ ]*ret[ ]*
|
42
gas/testsuite/gas/i386/tlsd.s
Normal file
42
gas/testsuite/gas/i386/tlsd.s
Normal file
@ -0,0 +1,42 @@
|
||||
.section ".tdata", "awT", @progbits
|
||||
.globl foo, baz
|
||||
.hidden baz
|
||||
foo: .long 25
|
||||
bar: .long 27
|
||||
baz: .long 29
|
||||
.text
|
||||
.globl fn
|
||||
.type fn,@function
|
||||
fn:
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
pushl %ebx
|
||||
pushl %eax
|
||||
call 1f
|
||||
1: popl %ebx
|
||||
addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
|
||||
|
||||
/* Dynamic TLS model, foo not known to be in the current object */
|
||||
leal foo@TLSGD(,%ebx,1), %eax
|
||||
call ___tls_get_addr@PLT
|
||||
/* %eax now contains &foo */
|
||||
|
||||
/* Dynamic TLS model, bar and baz known to be in the current object */
|
||||
leal bar@TLSLDM(%ebx), %eax
|
||||
call ___tls_get_addr@PLT
|
||||
|
||||
/* Just show that there can be arbitrary instructions here */
|
||||
leal 0(%edi, 1), %edi
|
||||
|
||||
leal bar@DTPOFF(%eax), %edx
|
||||
/* %edx now contains &bar */
|
||||
|
||||
/* Again, arbitrary instructions */
|
||||
leal 0(%esi, 1), %esi
|
||||
|
||||
leal baz@DTPOFF(%eax), %ecx
|
||||
/* %ecx now contains &baz */
|
||||
|
||||
movl -4(%ebp), %ebx
|
||||
leave
|
||||
ret
|
31
gas/testsuite/gas/i386/tlsnopic.d
Normal file
31
gas/testsuite/gas/i386/tlsnopic.d
Normal file
@ -0,0 +1,31 @@
|
||||
#objdump: -dr
|
||||
#name: i386 non-pic tls
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
0+000 <fn>:
|
||||
0: 8b 15 00 00 00 00 [ ]*mov 0x0,%edx
|
||||
[ ]+2: R_386_32 .text
|
||||
6: 81 c2 08 00 00 00 [ ]*add \$0x8,%edx
|
||||
[ ]+8: R_386_GOTPC _GLOBAL_OFFSET_TABLE_
|
||||
c: 65 a1 00 00 00 00 [ ]*mov %gs:0x0,%eax
|
||||
12: 2b 82 00 00 00 00 [ ]*sub 0x0\(%edx\),%eax
|
||||
[ ]+14: R_386_TLS_IE_32 foo
|
||||
18: 65 a1 00 00 00 00 [ ]*mov %gs:0x0,%eax
|
||||
1e: 2d 00 00 00 00 [ ]*sub \$0x0,%eax
|
||||
[ ]+1f: R_386_TLS_LE_32 bar
|
||||
23: 65 8b 0d 00 00 00 00 [ ]*mov %gs:0x0,%ecx
|
||||
2a: 90 [ ]*nop[ ]*
|
||||
2b: 81 e9 00 00 00 00 [ ]*sub \$0x0,%ecx
|
||||
[ ]+2d: R_386_TLS_LE_32 baz
|
||||
31: 65 8b 0d 00 00 00 00 [ ]*mov %gs:0x0,%ecx
|
||||
38: 90 [ ]*nop
|
||||
39: 90 [ ]*nop
|
||||
3a: 8d 81 00 00 00 00 [ ]*lea 0x0\(%ecx\),%eax
|
||||
[ ]+3c: R_386_TLS_LE var
|
||||
40: 90 [ ]*nop
|
||||
41: 8d 91 00 00 00 00 lea 0x0\(%ecx\),%edx
|
||||
[ ]+43: R_386_TLS_LE var2
|
||||
47: c3 [ ]*ret[ ]*
|
45
gas/testsuite/gas/i386/tlsnopic.s
Normal file
45
gas/testsuite/gas/i386/tlsnopic.s
Normal file
@ -0,0 +1,45 @@
|
||||
.section ".tdata", "awT", @progbits
|
||||
.globl baz
|
||||
.hidden baz
|
||||
.globl var
|
||||
.hidden var2
|
||||
bar: .long 27
|
||||
baz: .long 29
|
||||
var: .long 31
|
||||
var2: .long 33
|
||||
.text
|
||||
.globl fn
|
||||
.type fn,@function
|
||||
fn:
|
||||
/* Main binary, no PIC */
|
||||
1: movl 1b, %edx
|
||||
addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %edx
|
||||
|
||||
/* foo can be anywhere in startup TLS */
|
||||
movl %gs:0, %eax
|
||||
subl foo@GOTTPOFF(%edx), %eax
|
||||
/* %eax now contains &foo */
|
||||
|
||||
/* bar only in the main program */
|
||||
movl %gs:0, %eax
|
||||
subl $bar@TPOFF, %eax
|
||||
/* %eax now contains &bar */
|
||||
|
||||
/* baz only in the main program */
|
||||
movl %gs:0, %ecx
|
||||
/* Arbitrary instructions in between */
|
||||
nop
|
||||
subl $baz@TPOFF, %ecx
|
||||
/* %ecx now contains &baz */
|
||||
|
||||
/* var and var2 only in the main program */
|
||||
movl %gs:0, %ecx
|
||||
/* Arbitrary instructions in between */
|
||||
nop
|
||||
nop
|
||||
leal var@NTPOFF(%ecx), %eax
|
||||
/* Arbitrary instructions in between */
|
||||
nop
|
||||
leal var2@NTPOFF(%ecx), %edx
|
||||
|
||||
ret
|
23
gas/testsuite/gas/i386/tlspic.d
Normal file
23
gas/testsuite/gas/i386/tlspic.d
Normal file
@ -0,0 +1,23 @@
|
||||
#objdump: -dr
|
||||
#name: i386 non-pic tls
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
0+000 <fn>:
|
||||
0: 55 [ ]*push %ebp
|
||||
1: 89 e5 [ ]*mov %esp,%ebp
|
||||
3: 53 [ ]*push %ebx
|
||||
4: 50 [ ]*push %eax
|
||||
5: e8 00 00 00 00 [ ]*call a <fn\+0xa>
|
||||
a: 5b [ ]*pop %ebx
|
||||
b: 81 c3 03 00 00 00 [ ]*add \$0x3,%ebx
|
||||
[ ]+d: R_386_GOTPC _GLOBAL_OFFSET_TABLE_
|
||||
11: 65 a1 00 00 00 00 [ ]*mov %gs:0x0,%eax
|
||||
17: 8d 76 00 [ ]*lea 0x0\(%esi\),%esi
|
||||
1a: 2b 83 00 00 00 00 [ ]*sub 0x0\(%ebx\),%eax
|
||||
[ ]+1c: R_386_TLS_IE_32 foo
|
||||
20: 8b 5d fc [ ]*mov 0xfffffffc\(%ebp\),%ebx
|
||||
23: c9 [ ]*leave[ ]*
|
||||
24: c3 [ ]*ret[ ]*
|
27
gas/testsuite/gas/i386/tlspic.s
Normal file
27
gas/testsuite/gas/i386/tlspic.s
Normal file
@ -0,0 +1,27 @@
|
||||
.section ".tdata", "awT", @progbits
|
||||
.globl foo
|
||||
foo: .long 25
|
||||
.text
|
||||
.globl fn
|
||||
.type fn,@function
|
||||
fn:
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
pushl %ebx
|
||||
pushl %eax
|
||||
call 1f
|
||||
1: popl %ebx
|
||||
addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
|
||||
|
||||
/* foo can be anywhere in the startup TLS */
|
||||
movl %gs:0, %eax
|
||||
|
||||
/* Arbitrary instructions in between */
|
||||
leal 0(%esi, 1), %esi
|
||||
|
||||
subl foo@GOTTPOFF(%ebx), %eax
|
||||
/* %eax now contains &foo */
|
||||
|
||||
movl -4(%ebp), %ebx
|
||||
leave
|
||||
ret
|
@ -35,4 +35,5 @@ if [istarget "ia64-*"] then {
|
||||
run_dump_test "dv-mutex"
|
||||
run_dump_test "dv-safe"
|
||||
run_dump_test "dv-srlz"
|
||||
run_dump_test "tls"
|
||||
}
|
||||
|
53
gas/testsuite/gas/ia64/tls.d
Normal file
53
gas/testsuite/gas/ia64/tls.d
Normal file
@ -0,0 +1,53 @@
|
||||
#objdump: -dr
|
||||
#name: ia64 tls
|
||||
|
||||
.*: +file format .*
|
||||
|
||||
Disassembly of section \.text:
|
||||
|
||||
0000000000000000 <foo>:
|
||||
0: 0d 20 21 0a 80 05 \[MFI\] alloc r36=ar\.pfs,8,5,0
|
||||
2: LTOFF_TPREL22 x
|
||||
6: 00 00 00 02 00 00 nop\.f 0x0
|
||||
c: 04 08 00 90 addl r32=0,r1;;
|
||||
10: 0b 00 01 40 18 10 \[MMI\] ld8 r32=\[r32\];;
|
||||
16: 10 02 35 00 40 00 add r33=r32,r13
|
||||
1c: 00 00 04 00 nop\.i 0x0;;
|
||||
20: 0b 10 00 1a 00 21 \[MMI\] mov r2=r13;;
|
||||
21: TPREL22 y
|
||||
26: 10 02 08 00 48 00 addl r33=0,r2
|
||||
2c: 00 00 04 00 nop\.i 0x0;;
|
||||
30: 01 00 01 02 00 21 \[MII\] mov r32=r1
|
||||
31: LTOFF_DTPMOD22 z
|
||||
32: LTOFF_DTPREL22 z
|
||||
36: 50 02 04 00 48 c0 addl r37=0,r1
|
||||
3c: 04 08 00 90 addl r38=0,r1;;
|
||||
40: 19 28 01 4a 18 10 \[MMB\] ld8 r37=\[r37\]
|
||||
42: PCREL21B __tls_get_addr
|
||||
46: 60 02 98 30 20 00 ld8 r38=\[r38\]
|
||||
4c: 08 00 00 50 br\.call\.sptk\.many b0=40 <foo\+0x40>;;
|
||||
50: 0b 08 00 40 00 21 \[MMI\] mov r1=r32;;
|
||||
51: LTOFF_DTPMOD22 a
|
||||
52: DTPREL22 a
|
||||
56: 50 02 04 00 48 c0 addl r37=0,r1
|
||||
5c: 04 00 00 90 mov r38=0;;
|
||||
60: 1d 28 01 4a 18 10 \[MFB\] ld8 r37=\[r37\]
|
||||
62: PCREL21B __tls_get_addr
|
||||
66: 00 00 00 02 00 00 nop\.f 0x0
|
||||
6c: 08 00 00 50 br\.call\.sptk\.many b0=60 <foo\+0x60>;;
|
||||
70: 0b 08 00 40 00 21 \[MMI\] mov r1=r32;;
|
||||
71: LTOFF_DTPMOD22 b
|
||||
76: 50 02 04 00 48 c0 addl r37=0,r1
|
||||
7c: 04 00 00 84 mov r38=r0;;
|
||||
80: 1d 28 01 4a 18 10 \[MFB\] ld8 r37=\[r37\]
|
||||
82: PCREL21B __tls_get_addr
|
||||
86: 00 00 00 02 00 00 nop\.f 0x0
|
||||
8c: 08 00 00 50 br\.call\.sptk\.many b0=80 <foo\+0x80>;;
|
||||
90: 02 08 00 40 00 21 \[MII\] mov r1=r32
|
||||
92: DTPREL22 b
|
||||
96: 20 00 20 00 42 20 mov r2=r8;;
|
||||
9c: 04 10 00 90 addl r33=0,r2
|
||||
a0: 1d 10 01 04 00 24 \[MFB\] addl r34=0,r2
|
||||
a0: DTPREL22 c
|
||||
a6: 00 00 00 02 00 80 nop\.f 0x0
|
||||
ac: 08 00 84 00 br\.ret\.sptk\.many b0;;
|
64
gas/testsuite/gas/ia64/tls.s
Normal file
64
gas/testsuite/gas/ia64/tls.s
Normal file
@ -0,0 +1,64 @@
|
||||
.section ".tdata", "awT", @progbits
|
||||
.align 16
|
||||
.global x#, y#, z#, a#, b#, c#
|
||||
.protected a#, b#, c#
|
||||
.type x#,@object
|
||||
.size x#,4
|
||||
x: data4 1
|
||||
.type y#,@object
|
||||
.size y#,4
|
||||
y: data4 2
|
||||
.type z#,@object
|
||||
.size z#,4
|
||||
z: data4 3
|
||||
.align 8
|
||||
.type a#,@object
|
||||
.size a#,8
|
||||
a: data8 4
|
||||
.type b#,@object
|
||||
.size b#,8
|
||||
b: data8 5
|
||||
.type c#,@object
|
||||
.size c#,1
|
||||
c: data1 6
|
||||
|
||||
.text
|
||||
.align 16
|
||||
.global foo#
|
||||
.proc foo#
|
||||
foo:
|
||||
.prologue
|
||||
alloc r36 = ar.pfs, 0, 5, 3, 0
|
||||
.body
|
||||
addl loc0 = @ltoff(@tprel(x)), gp;;
|
||||
ld8 loc0 = [loc0];;
|
||||
add loc1 = loc0, r13;;
|
||||
|
||||
mov r2 = r13;;
|
||||
addl loc1 = @tprel(y), r2;;
|
||||
|
||||
mov loc0 = gp
|
||||
addl out0 = @ltoff(@dtpmod(z)), gp
|
||||
addl out1 = @ltoff(@dtprel(z)), gp;;
|
||||
ld8 out0 = [out0]
|
||||
ld8 out1 = [out1]
|
||||
br.call.sptk.many b0 = __tls_get_addr;;
|
||||
mov gp = loc0;;
|
||||
|
||||
addl out0 = @ltoff(@dtpmod(a)), gp
|
||||
addl out1 = @dtprel(a), r0;;
|
||||
ld8 out0 = [out0]
|
||||
br.call.sptk.many b0 = __tls_get_addr;;
|
||||
mov gp = loc0;;
|
||||
|
||||
addl out0 = @ltoff(@dtpmod(b)), gp
|
||||
mov out1 = r0;;
|
||||
ld8 out0 = [out0]
|
||||
br.call.sptk.many b0 = __tls_get_addr;;
|
||||
mov gp = loc0
|
||||
mov r2 = ret0;;
|
||||
addl loc1 = @dtprel(b), r2
|
||||
addl loc2 = @dtprel(c), r2
|
||||
|
||||
br.ret.sptk.many b0
|
||||
.endp foo#
|
@ -889,6 +889,13 @@ adjust_reloc_syms (abfd, sec, xxx)
|
||||
symbol_mark_used_in_reloc (fixp->fx_addsy);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Never adjust a reloc against TLS local symbol. */
|
||||
if (symsec->flags & SEC_THREAD_LOCAL)
|
||||
{
|
||||
symbol_mark_used_in_reloc (fixp->fx_addsy);
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Is there some other reason we can't adjust this one? (E.g.,
|
||||
|
@ -1,3 +1,9 @@
|
||||
2002-05-23 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* elf/common.h (PT_TLS, SHF_TLS, STT_TLS, DF_STATIC_TLS): Define.
|
||||
* elf/ia64.h (R_IA64_LTOFF_TPREL22): Renamed from R_IA64_LTOFF_TP22.
|
||||
* elf/i386.h: Add TLS relocs.
|
||||
|
||||
2002-05-21 H.J. Lu (hjl@gnu.org)
|
||||
|
||||
* bfdlink.h (bfd_link_info): Add allow_multiple_definition.
|
||||
|
@ -254,6 +254,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
#define PT_NOTE 4 /* Auxiliary information */
|
||||
#define PT_SHLIB 5 /* Reserved, unspecified semantics */
|
||||
#define PT_PHDR 6 /* Entry for header table itself */
|
||||
#define PT_TLS 7 /* Thread local storage segment */
|
||||
#define PT_LOOS 0x60000000 /* OS-specific */
|
||||
#define PT_HIOS 0x6fffffff /* OS-specific */
|
||||
#define PT_LOPROC 0x70000000 /* Processor-specific */
|
||||
@ -322,6 +323,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
#define SHF_LINK_ORDER (1 << 7) /* Preserve section ordering when linking */
|
||||
#define SHF_OS_NONCONFORMING (1 << 8) /* OS specific processing required */
|
||||
#define SHF_GROUP (1 << 9) /* Member of a section group */
|
||||
#define SHF_TLS (1 << 10) /* Thread local storage section */
|
||||
|
||||
/* #define SHF_MASKOS 0x0F000000 *//* OS-specific semantics */
|
||||
#define SHF_MASKOS 0x0FF00000 /* New value, Oct 4, 1999 Draft */
|
||||
@ -417,6 +419,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
#define STT_SECTION 3 /* Symbol associated with a section */
|
||||
#define STT_FILE 4 /* Symbol gives a file name */
|
||||
#define STT_COMMON 5 /* An uninitialised common block */
|
||||
#define STT_TLS 6 /* Thread local data object */
|
||||
#define STT_LOOS 10 /* OS-specific semantics */
|
||||
#define STT_HIOS 12 /* OS-specific semantics */
|
||||
#define STT_LOPROC 13 /* Application-specific semantics */
|
||||
@ -585,6 +588,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
#define DF_SYMBOLIC (1 << 1)
|
||||
#define DF_TEXTREL (1 << 2)
|
||||
#define DF_BIND_NOW (1 << 3)
|
||||
#define DF_STATIC_TLS (1 << 4)
|
||||
|
||||
/* These constants are used for the version number of a Elf32_Verdef
|
||||
structure. */
|
||||
|
@ -34,12 +34,31 @@ START_RELOC_NUMBERS (elf_i386_reloc_type)
|
||||
RELOC_NUMBER (R_386_RELATIVE, 8) /* Adjust by program base */
|
||||
RELOC_NUMBER (R_386_GOTOFF, 9) /* 32 bit offset to GOT */
|
||||
RELOC_NUMBER (R_386_GOTPC, 10) /* 32 bit PC relative offset to GOT */
|
||||
FAKE_RELOC (FIRST_INVALID_RELOC, 11)
|
||||
FAKE_RELOC (LAST_INVALID_RELOC, 19)
|
||||
RELOC_NUMBER (R_386_32PLT, 11) /* Used by Sun */
|
||||
FAKE_RELOC (FIRST_INVALID_RELOC, 12)
|
||||
FAKE_RELOC (LAST_INVALID_RELOC, 16)
|
||||
RELOC_NUMBER (R_386_TLS_LE, 17)
|
||||
RELOC_NUMBER (R_386_TLS_GD, 18)
|
||||
RELOC_NUMBER (R_386_TLS_LDM, 19)
|
||||
RELOC_NUMBER (R_386_16, 20)
|
||||
RELOC_NUMBER (R_386_PC16, 21)
|
||||
RELOC_NUMBER (R_386_8, 22)
|
||||
RELOC_NUMBER (R_386_PC8, 23)
|
||||
RELOC_NUMBER (R_386_TLS_GD_32, 24)
|
||||
RELOC_NUMBER (R_386_TLS_GD_PUSH, 25)
|
||||
RELOC_NUMBER (R_386_TLS_GD_CALL, 26)
|
||||
RELOC_NUMBER (R_386_TLS_GD_POP, 27)
|
||||
RELOC_NUMBER (R_386_TLS_LDM_32, 28)
|
||||
RELOC_NUMBER (R_386_TLS_LDM_PUSH, 29)
|
||||
RELOC_NUMBER (R_386_TLS_LDM_CALL, 30)
|
||||
RELOC_NUMBER (R_386_TLS_LDM_POP, 31)
|
||||
RELOC_NUMBER (R_386_TLS_LDO_32, 32)
|
||||
RELOC_NUMBER (R_386_TLS_IE_32, 33)
|
||||
RELOC_NUMBER (R_386_TLS_LE_32, 34)
|
||||
RELOC_NUMBER (R_386_TLS_DTPMOD32, 35)
|
||||
RELOC_NUMBER (R_386_TLS_DTPOFF32, 36)
|
||||
RELOC_NUMBER (R_386_TLS_TPOFF32, 37)
|
||||
|
||||
/* These are GNU extensions to enable C++ vtable garbage collection. */
|
||||
RELOC_NUMBER (R_386_GNU_VTINHERIT, 250)
|
||||
RELOC_NUMBER (R_386_GNU_VTENTRY, 251)
|
||||
|
@ -192,7 +192,7 @@ START_RELOC_NUMBERS (elf_ia64_reloc_type)
|
||||
RELOC_NUMBER (R_IA64_TPREL64MSB, 0x96) /* @tprel(sym+add), data8 MSB */
|
||||
RELOC_NUMBER (R_IA64_TPREL64LSB, 0x97) /* @tprel(sym+add), data8 LSB */
|
||||
|
||||
RELOC_NUMBER (R_IA64_LTOFF_TP22, 0x9a) /* @ltoff(@tprel(s+a)), add imm22 */
|
||||
RELOC_NUMBER (R_IA64_LTOFF_TPREL22, 0x9a) /* @ltoff(@tprel(s+a)), add imm22 */
|
||||
|
||||
RELOC_NUMBER (R_IA64_DTPMOD64MSB, 0xa6) /* @dtpmod(sym+add), data8 MSB */
|
||||
RELOC_NUMBER (R_IA64_DTPMOD64LSB, 0xa7) /* @dtpmod(sym+add), data8 LSB */
|
||||
|
@ -1,3 +1,12 @@
|
||||
2002-05-23 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* scripttempl/elf.sc: Add .rel{,a}.t{bss,data}, .tdata and .tbss.
|
||||
* ldlang.c (lang_add_section): Set SEC_THREAD_LOCAL for
|
||||
output section if necessary. Handle .tbss.
|
||||
(lang_size_sections): Clear _raw_size for .tbss section
|
||||
(it allocates space in PT_TLS segment only).
|
||||
* ldwrite.c (build_link_order): Build link order for .tbss too.
|
||||
|
||||
2002-05-23 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* configure.in: Correct spelling of AC_PREREQ.
|
||||
|
@ -1210,6 +1210,10 @@ lang_add_section (ptr, section, output, file)
|
||||
flags &= ~ (SEC_MERGE | SEC_STRINGS);
|
||||
}
|
||||
|
||||
/* For now make .tbss normal section. */
|
||||
if (flags & SEC_THREAD_LOCAL)
|
||||
flags |= SEC_LOAD;
|
||||
|
||||
section->output_section->flags |= flags;
|
||||
|
||||
if (flags & SEC_MERGE)
|
||||
@ -3010,6 +3014,9 @@ lang_size_sections_1 (s, output_section_statement, prev, fill, dot, relax)
|
||||
|
||||
if (bfd_is_abs_section (os->bfd_section))
|
||||
ASSERT (after == os->bfd_section->vma);
|
||||
else if ((os->bfd_section->flags & SEC_HAS_CONTENTS) == 0
|
||||
&& (os->bfd_section->flags & SEC_THREAD_LOCAL))
|
||||
os->bfd_section->_raw_size = 0;
|
||||
else
|
||||
os->bfd_section->_raw_size =
|
||||
(after - os->bfd_section->vma) * opb;
|
||||
|
@ -233,7 +233,9 @@ build_link_order (statement)
|
||||
|
||||
ASSERT (output_section->owner == output_bfd);
|
||||
|
||||
if ((output_section->flags & SEC_HAS_CONTENTS) != 0)
|
||||
if ((output_section->flags & SEC_HAS_CONTENTS) != 0
|
||||
|| ((output_section->flags & SEC_LOAD) != 0
|
||||
&& (output_section->flags & SEC_THREAD_LOCAL)))
|
||||
{
|
||||
struct bfd_link_order *link_order;
|
||||
|
||||
|
@ -60,6 +60,8 @@
|
||||
# .sdata2 .gnu.linkonce.s2.foo
|
||||
# .sbss2 .gnu.linkonce.sb2.foo
|
||||
# .debug_info .gnu.linkonce.wi.foo
|
||||
# .tdata .gnu.linkonce.td.foo
|
||||
# .tbss .gnu.linkonce.tb.foo
|
||||
#
|
||||
# Each of these can also have corresponding .rel.* and .rela.* sections.
|
||||
|
||||
@ -208,6 +210,10 @@ eval $COMBRELOCCAT <<EOF
|
||||
${OTHER_READONLY_RELOC_SECTIONS}
|
||||
.rel.data ${RELOCATING-0} : { *(.rel.data${RELOCATING+ .rel.data.* .rel.gnu.linkonce.d.*}) }
|
||||
.rela.data ${RELOCATING-0} : { *(.rela.data${RELOCATING+ .rela.data.* .rela.gnu.linkonce.d.*}) }
|
||||
.rel.tdata ${RELOCATING-0} : { *(.rel.tdata${RELOCATING+ .rel.tdata.* .rel.gnu.linkonce.td.*}) }
|
||||
.rela.tdata ${RELOCATING-0} : { *(.rela.tdata${RELOCATING+ .rela.tdata.* .rela.gnu.linkonce.td.*}) }
|
||||
.rel.tbss ${RELOCATING-0} : { *(.rel.tbss${RELOCATING+ .rel.tbss.* .rel.gnu.linkonce.tb.*}) }
|
||||
.rela.tbss ${RELOCATING-0} : { *(.rela.tbss${RELOCATING+ .rela.tbss.* .rela.gnu.linkonce.tb.*}) }
|
||||
.rel.ctors ${RELOCATING-0} : { *(.rel.ctors) }
|
||||
.rela.ctors ${RELOCATING-0} : { *(.rela.ctors) }
|
||||
.rel.dtors ${RELOCATING-0} : { *(.rel.dtors) }
|
||||
@ -304,6 +310,8 @@ cat <<EOF
|
||||
${CONSTRUCTING+SORT(CONSTRUCTORS)}
|
||||
}
|
||||
.data1 ${RELOCATING-0} : { *(.data1) }
|
||||
.tdata ${RELOCATING-0} : { *(.tdata${RELOCATING+ .tdata.* .gnu.linkonce.td.*}) }
|
||||
.tbss ${RELOCATING-0} : { *(.tbss${RELOCATING+ .tbss.* .gnu.linkonce.tb.*) *(.tcommon}) }
|
||||
.eh_frame ${RELOCATING-0} : { KEEP (*(.eh_frame)) }
|
||||
.gcc_except_table ${RELOCATING-0} : { *(.gcc_except_table) }
|
||||
${WRITABLE_RODATA+${RODATA}}
|
||||
|
Loading…
Reference in New Issue
Block a user