* bfd-in.h (_bfd_elf_tls_setup): Declare.

* bfd-in2.h: Regenerate.
	* elf-bfd.h (struct elf_link_tls_segment): Delete.
	(struct elf_link_hash_table): Add tls_sec and tls_size.
	* elf.c (_bfd_elf_link_hash_table_init): Init tls_sec and tls_size.
	* elflink.c (_bfd_elf_tls_setup): New function.
	* elflink.h (struct elf_final_link_info): Remove first_tls_sec.
	(elf_bfd_final_link): Don't set first_tls_sec here.  Update code
	saving tls segment info, round segment size up.
	(elf_link_output_extsym): Adjust code using tls segment info.
	(elf_link_input_bfd): Likewise.
	* elf32-i386.c (dtpoff_base, tpoff): Likewise.
	* elf32-s390.c (dtpoff_base, tpoff): Likewise.
	* elf32-sh.c (dtpoff_base, tpoff): Likewise.
	* elf32-sparc.c (dtpoff_base, tpoff): Likewise.
	* elf64-s390.c (dtpoff_base, tpoff): Likewise.
	* elf64-x86-64.c (dtpoff_base, tpoff): Likewise.
	* elfxx-ia64.c (elfNN_ia64_tprel_base): Likewise.
	(elfNN_ia64_dtprel_base): Likewise.
	* elf64-alpha.c (alpha_get_dtprel_base): Likewise.
	(alpha_get_tprel_base): Likewise.
	(struct alpha_relax_info): Remove tls_segment.
	(elf64_alpha_relax_got_load): Adjust invocation of
	alpha_get_dtprel_base and alpha_get_tprel_base.
	(elf64_alpha_relax_tls_get_addr): Likewise.
	(elf64_alpha_relax_section): Likewise.
	(elf64_alpha_relocate_section): Likewise.
	(elf64_alpha_relax_find_tls_segment): Delete.
	* elf32-ppc.c (struct ppc_elf_link_hash_table): Remove tls_sec.
	(ppc_elf_tls_setup): Call _bfd_elf_tls_setup.  Return section.
	(ppc_elf_relocate_section): Adjust to use elf.tls_sec.
	* elf32-ppc.h (ppc_elf_tls_setup): Update.
	* elf64-ppc.c (struct ppc_link_hash_table): Remove tls_sec.
	(ppc64_elf_tls_setup): Call _bfd_elf_tls_setup.  Return section.
	(ppc64_elf_tls_optimize): Adjust to use elf.tls_sec.
	(ppc64_elf_relocate_section): Likewise.
	* elf64-ppc.h (ppc64_elf_tls_setup): Update.

	* emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation): Call
	_bfd_elf_tls_setup.
This commit is contained in:
Alan Modra 2003-11-04 06:16:39 +00:00
parent 4d100af478
commit e1918d2387
21 changed files with 193 additions and 222 deletions

View File

@ -1,3 +1,43 @@
2003-11-04 Alan Modra <amodra@bigpond.net.au>
* bfd-in.h (_bfd_elf_tls_setup): Declare.
* bfd-in2.h: Regenerate.
* elf-bfd.h (struct elf_link_tls_segment): Delete.
(struct elf_link_hash_table): Add tls_sec and tls_size.
* elf.c (_bfd_elf_link_hash_table_init): Init tls_sec and tls_size.
* elflink.c (_bfd_elf_tls_setup): New function.
* elflink.h (struct elf_final_link_info): Remove first_tls_sec.
(elf_bfd_final_link): Don't set first_tls_sec here. Update code
saving tls segment info, round segment size up.
(elf_link_output_extsym): Adjust code using tls segment info.
(elf_link_input_bfd): Likewise.
* elf32-i386.c (dtpoff_base, tpoff): Likewise.
* elf32-s390.c (dtpoff_base, tpoff): Likewise.
* elf32-sh.c (dtpoff_base, tpoff): Likewise.
* elf32-sparc.c (dtpoff_base, tpoff): Likewise.
* elf64-s390.c (dtpoff_base, tpoff): Likewise.
* elf64-x86-64.c (dtpoff_base, tpoff): Likewise.
* elfxx-ia64.c (elfNN_ia64_tprel_base): Likewise.
(elfNN_ia64_dtprel_base): Likewise.
* elf64-alpha.c (alpha_get_dtprel_base): Likewise.
(alpha_get_tprel_base): Likewise.
(struct alpha_relax_info): Remove tls_segment.
(elf64_alpha_relax_got_load): Adjust invocation of
alpha_get_dtprel_base and alpha_get_tprel_base.
(elf64_alpha_relax_tls_get_addr): Likewise.
(elf64_alpha_relax_section): Likewise.
(elf64_alpha_relocate_section): Likewise.
(elf64_alpha_relax_find_tls_segment): Delete.
* elf32-ppc.c (struct ppc_elf_link_hash_table): Remove tls_sec.
(ppc_elf_tls_setup): Call _bfd_elf_tls_setup. Return section.
(ppc_elf_relocate_section): Adjust to use elf.tls_sec.
* elf32-ppc.h (ppc_elf_tls_setup): Update.
* elf64-ppc.c (struct ppc_link_hash_table): Remove tls_sec.
(ppc64_elf_tls_setup): Call _bfd_elf_tls_setup. Return section.
(ppc64_elf_tls_optimize): Adjust to use elf.tls_sec.
(ppc64_elf_relocate_section): Likewise.
* elf64-ppc.h (ppc64_elf_tls_setup): Update.
2003-11-03 Daniel Jacobowitz <drow@mvista.com>
* elf-bfd.h (struct elf_backend_data): Remove plt_header_size.

View File

@ -677,6 +677,9 @@ extern int bfd_get_arch_size
extern int bfd_get_sign_extend_vma
(bfd *);
extern struct bfd_section *_bfd_elf_tls_setup
(bfd *, struct bfd_link_info *);
extern bfd_boolean bfd_m68k_elf32_create_embedded_relocs
(bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *, char **);
extern bfd_boolean bfd_mips_elf32_create_embedded_relocs

View File

@ -684,6 +684,9 @@ extern int bfd_get_arch_size
extern int bfd_get_sign_extend_vma
(bfd *);
extern struct bfd_section *_bfd_elf_tls_setup
(bfd *, struct bfd_link_info *);
extern bfd_boolean bfd_m68k_elf32_create_embedded_relocs
(bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *, char **);
extern bfd_boolean bfd_mips_elf32_create_embedded_relocs

View File

@ -309,14 +309,6 @@ struct eh_frame_hdr_info
bfd_boolean table;
};
/* 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
@ -377,8 +369,9 @@ struct elf_link_hash_table
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;
/* Cached first output tls section and size of PT_TLS segment. */
asection *tls_sec;
bfd_size_type tls_size;
/* A linked list of BFD's loaded in the link. */
struct elf_link_loaded_list *loaded;

View File

@ -1444,7 +1444,8 @@ _bfd_elf_link_hash_table_init
memset (&table->eh_info, 0, sizeof (table->eh_info));
table->dynlocal = NULL;
table->runpath = NULL;
table->tls_segment = NULL;
table->tls_sec = NULL;
table->tls_size = 0;
table->loaded = NULL;
ret = _bfd_link_hash_table_init (&table->root, abfd, newfunc);

View File

@ -1953,10 +1953,10 @@ elf_i386_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
static bfd_vma
dtpoff_base (struct bfd_link_info *info)
{
/* If tls_segment is NULL, we should have signalled an error already. */
if (elf_hash_table (info)->tls_segment == NULL)
/* If tls_sec is NULL, we should have signalled an error already. */
if (elf_hash_table (info)->tls_sec == NULL)
return 0;
return elf_hash_table (info)->tls_segment->start;
return elf_hash_table (info)->tls_sec->vma;
}
/* Return the relocation value for @tpoff relocation
@ -1965,14 +1965,12 @@ dtpoff_base (struct bfd_link_info *info)
static bfd_vma
tpoff (struct bfd_link_info *info, bfd_vma address)
{
struct elf_link_tls_segment *tls_segment
= elf_hash_table (info)->tls_segment;
struct elf_link_hash_table *htab = elf_hash_table (info);
/* If tls_segment is NULL, we should have signalled an error already. */
if (tls_segment == NULL)
/* If tls_sec is NULL, we should have signalled an error already. */
if (htab->tls_sec == NULL)
return 0;
return (align_power (tls_segment->size, tls_segment->align)
+ tls_segment->start - address);
return htab->tls_size + htab->tls_sec->vma - address;
}
/* Relocate an i386 ELF section. */

View File

@ -205,9 +205,6 @@ struct ppc_elf_link_hash_table
elf_linker_section_t *sdata2;
asection *sbss;
/* Short-cut to first output tls section. */
asection *tls_sec;
/* Shortcut to .__tls_get_addr. */
struct elf_link_hash_entry *tls_get_addr;
@ -4184,25 +4181,18 @@ ppc_elf_gc_sweep_hook (bfd *abfd,
return TRUE;
}
/* Set htab->tls_sec and htab->tls_get_addr. */
/* Set htab->tls_get_addr and call the generic ELF tls_setup function. */
bfd_boolean
asection *
ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
{
asection *tls;
struct ppc_elf_link_hash_table *htab;
htab = ppc_elf_hash_table (info);
htab->tls_get_addr = elf_link_hash_lookup (&htab->elf, "__tls_get_addr",
FALSE, FALSE, TRUE);
for (tls = obfd->sections; tls != NULL; tls = tls->next)
if ((tls->flags & (SEC_THREAD_LOCAL | SEC_LOAD))
== (SEC_THREAD_LOCAL | SEC_LOAD))
break;
htab->tls_sec = tls;
return tls != NULL;
return _bfd_elf_tls_setup (obfd, info);
}
/* Run through all the TLS relocs looking for optimization
@ -4917,8 +4907,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
{
/* Was an LD reloc. */
r_symndx = 0;
rel->r_addend = htab->tls_sec->vma + DTP_OFFSET;
rel[1].r_addend = htab->tls_sec->vma + DTP_OFFSET;
rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
rel[1].r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
}
r_type = R_PPC_TPREL16_HA;
rel->r_info = ELF32_R_INFO (r_symndx, r_type);
@ -5156,7 +5146,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
{
outrel.r_addend += relocation;
if (tls_ty & (TLS_GD | TLS_DTPREL | TLS_TPREL))
outrel.r_addend -= htab->tls_sec->vma;
outrel.r_addend -= htab->elf.tls_sec->vma;
}
loc = htab->relgot->contents;
loc += (htab->relgot->reloc_count++
@ -5174,7 +5164,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
value = 1;
else if (tls_ty != 0)
{
value -= htab->tls_sec->vma + DTP_OFFSET;
value -= htab->elf.tls_sec->vma + DTP_OFFSET;
if (tls_ty == (TLS_TLS | TLS_TPREL))
value += DTP_OFFSET - TP_OFFSET;
@ -5262,7 +5252,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
case R_PPC_DTPREL16_LO:
case R_PPC_DTPREL16_HI:
case R_PPC_DTPREL16_HA:
addend -= htab->tls_sec->vma + DTP_OFFSET;
addend -= htab->elf.tls_sec->vma + DTP_OFFSET;
break;
/* Relocations that may need to be propagated if this is a shared
@ -5271,18 +5261,18 @@ ppc_elf_relocate_section (bfd *output_bfd,
case R_PPC_TPREL16_LO:
case R_PPC_TPREL16_HI:
case R_PPC_TPREL16_HA:
addend -= htab->tls_sec->vma + TP_OFFSET;
addend -= htab->elf.tls_sec->vma + TP_OFFSET;
/* The TPREL16 relocs shouldn't really be used in shared
libs as they will result in DT_TEXTREL being set, but
support them anyway. */
goto dodyn;
case R_PPC_TPREL32:
addend -= htab->tls_sec->vma + TP_OFFSET;
addend -= htab->elf.tls_sec->vma + TP_OFFSET;
goto dodyn;
case R_PPC_DTPREL32:
addend -= htab->tls_sec->vma + DTP_OFFSET;
addend -= htab->elf.tls_sec->vma + DTP_OFFSET;
goto dodyn;
case R_PPC_DTPMOD32:

View File

@ -17,5 +17,5 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
bfd_boolean ppc_elf_tls_setup (bfd *, struct bfd_link_info *);
asection *ppc_elf_tls_setup (bfd *, struct bfd_link_info *);
bfd_boolean ppc_elf_tls_optimize (bfd *, struct bfd_link_info *);

View File

@ -2216,10 +2216,10 @@ static bfd_vma
dtpoff_base (info)
struct bfd_link_info *info;
{
/* If tls_segment is NULL, we should have signalled an error already. */
if (elf_hash_table (info)->tls_segment == NULL)
/* If tls_sec is NULL, we should have signalled an error already. */
if (elf_hash_table (info)->tls_sec == NULL)
return 0;
return elf_hash_table (info)->tls_segment->start;
return elf_hash_table (info)->tls_sec->vma;
}
/* Return the relocation value for @tpoff relocation
@ -2230,14 +2230,12 @@ tpoff (info, address)
struct bfd_link_info *info;
bfd_vma address;
{
struct elf_link_tls_segment *tls_segment
= elf_hash_table (info)->tls_segment;
struct elf_link_hash_table *htab = elf_hash_table (info);
/* If tls_segment is NULL, we should have signalled an error already. */
if (tls_segment == NULL)
/* If tls_sec is NULL, we should have signalled an error already. */
if (htab->tls_sec == NULL)
return 0;
return (align_power (tls_segment->size, tls_segment->align)
+ tls_segment->start - address);
return htab->tls_size + htab->tls_sec->vma - address;
}
/* Complain if TLS instruction relocation is against an invalid

View File

@ -6021,10 +6021,10 @@ sh_elf_get_relocated_section_contents (bfd *output_bfd,
static bfd_vma
dtpoff_base (struct bfd_link_info *info)
{
/* If tls_segment is NULL, we should have signalled an error already. */
if (elf_hash_table (info)->tls_segment == NULL)
/* If tls_sec is NULL, we should have signalled an error already. */
if (elf_hash_table (info)->tls_sec == NULL)
return 0;
return elf_hash_table (info)->tls_segment->start;
return elf_hash_table (info)->tls_sec->vma;
}
/* Return the relocation value for R_SH_TLS_TPOFF32.. */
@ -6032,12 +6032,12 @@ dtpoff_base (struct bfd_link_info *info)
static bfd_vma
tpoff (struct bfd_link_info *info, bfd_vma address)
{
/* If tls_segment is NULL, we should have signalled an error already. */
if (elf_hash_table (info)->tls_segment == NULL)
/* If tls_sec is NULL, we should have signalled an error already. */
if (elf_hash_table (info)->tls_sec == NULL)
return 0;
/* SH TLS ABI is variant I and static TLS block start just after tcbhead
structure which has 2 pointer fields. */
return (address - dtpoff_base (info) + 8);
return address - elf_hash_table (info)->tls_sec->vma + 8;
}
static asection *

View File

@ -2082,10 +2082,10 @@ static bfd_vma
dtpoff_base (info)
struct bfd_link_info *info;
{
/* If tls_segment is NULL, we should have signalled an error already. */
if (elf_hash_table (info)->tls_segment == NULL)
/* If tls_sec is NULL, we should have signalled an error already. */
if (elf_hash_table (info)->tls_sec == NULL)
return 0;
return elf_hash_table (info)->tls_segment->start;
return elf_hash_table (info)->tls_sec->vma;
}
/* Return the relocation value for @tpoff relocation
@ -2096,14 +2096,12 @@ tpoff (info, address)
struct bfd_link_info *info;
bfd_vma address;
{
struct elf_link_tls_segment *tls_segment
= elf_hash_table (info)->tls_segment;
struct elf_link_hash_table *htab = elf_hash_table (info);
/* If tls_segment is NULL, we should have signalled an error already. */
if (tls_segment == NULL)
/* If tls_sec is NULL, we should have signalled an error already. */
if (htab->tls_sec == NULL)
return 0;
return -(align_power (tls_segment->size, tls_segment->align)
+ tls_segment->start - address);
return address - htab->tls_size - htab->tls_sec->vma;
}
/* Relocate a SPARC ELF section. */

View File

@ -1158,13 +1158,15 @@ elf64_alpha_info_to_howto (abfd, cache_ptr, dst)
(r_type == R_ALPHA_TLSGD || r_type == R_ALPHA_TLSLDM ? 16 : 8)
/* This is PT_TLS segment p_vaddr. */
#define alpha_get_dtprel_base(tlss) \
((tlss)->start)
#define alpha_get_dtprel_base(info) \
(elf_hash_table (info)->tls_sec->vma)
/* Main program TLS (whose template starts at PT_TLS p_vaddr)
is assigned offset round(16, PT_TLS p_align). */
#define alpha_get_tprel_base(tlss) \
((tlss)->start - align_power ((bfd_vma) 16, (tlss)->align))
#define alpha_get_tprel_base(info) \
(elf_hash_table (info)->tls_sec->vma \
- align_power ((bfd_vma) 16, \
elf_hash_table (info)->tls_sec->alignment_power))
/* These functions do relaxation for Alpha ELF.
@ -1198,7 +1200,6 @@ struct alpha_relax_info
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *relocs, *relend;
struct bfd_link_info *link_info;
struct elf_link_tls_segment *tls_segment;
bfd_vma gp;
bfd *gotobj;
asection *tsec;
@ -1224,8 +1225,6 @@ static bfd_boolean elf64_alpha_relax_gprelhilo
static bfd_boolean elf64_alpha_relax_tls_get_addr
PARAMS((struct alpha_relax_info *info, bfd_vma symval,
Elf_Internal_Rela *irel, bfd_boolean));
static struct elf_link_tls_segment *elf64_alpha_relax_find_tls_segment
PARAMS((struct alpha_relax_info *, struct elf_link_tls_segment *));
static bfd_boolean elf64_alpha_relax_section
PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
bfd_boolean *again));
@ -1598,9 +1597,9 @@ elf64_alpha_relax_got_load (info, symval, irel, r_type)
{
bfd_vma dtp_base, tp_base;
BFD_ASSERT (info->tls_segment != NULL);
dtp_base = alpha_get_dtprel_base (info->tls_segment);
tp_base = alpha_get_tprel_base (info->tls_segment);
BFD_ASSERT (elf_hash_table (info->link_info)->tls_sec != NULL);
dtp_base = alpha_get_dtprel_base (info->link_info);
tp_base = alpha_get_tprel_base (info->link_info);
disp = symval - (r_type == R_ALPHA_GOTDTPREL ? dtp_base : tp_base);
}
@ -1845,8 +1844,8 @@ elf64_alpha_relax_tls_get_addr (info, symval, irel, is_gd)
bfd_vma tp_base;
bfd_signed_vma disp;
BFD_ASSERT (info->tls_segment != NULL);
tp_base = alpha_get_tprel_base (info->tls_segment);
BFD_ASSERT (elf_hash_table (info->link_info)->tls_sec != NULL);
tp_base = alpha_get_tprel_base (info->link_info);
disp = symval - tp_base;
if (disp >= -0x8000 && disp < 0x8000)
@ -1961,53 +1960,6 @@ elf64_alpha_relax_tls_get_addr (info, symval, irel, is_gd)
return TRUE;
}
static struct elf_link_tls_segment *
elf64_alpha_relax_find_tls_segment (info, seg)
struct alpha_relax_info *info;
struct elf_link_tls_segment *seg;
{
bfd *output_bfd = info->sec->output_section->owner;
asection *o;
unsigned int align;
bfd_vma base, end;
for (o = output_bfd->sections; o ; o = o->next)
if ((o->flags & SEC_THREAD_LOCAL) != 0
&& (o->flags & SEC_LOAD) != 0)
break;
if (!o)
return NULL;
base = o->vma;
align = 0;
do
{
bfd_vma size;
if (bfd_get_section_alignment (output_bfd, o) > align)
align = bfd_get_section_alignment (output_bfd, o);
size = o->_raw_size;
if (size == 0 && (o->flags & SEC_HAS_CONTENTS) == 0)
{
struct bfd_link_order *lo;
for (lo = o->link_order_head; lo ; lo = lo->next)
if (size < lo->offset + lo->size)
size = lo->offset + lo->size;
}
end = o->vma + size;
o = o->next;
}
while (o && (o->flags & SEC_THREAD_LOCAL));
seg->start = base;
seg->size = end - base;
seg->align = align;
return seg;
}
static bfd_boolean
elf64_alpha_relax_section (abfd, sec, link_info, again)
bfd *abfd;
@ -2021,7 +1973,6 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
Elf_Internal_Sym *isymbuf = NULL;
struct alpha_elf_got_entry **local_got_entries;
struct alpha_relax_info info;
struct elf_link_tls_segment tls_segment;
/* We are not currently changing any sizes, so only one pass. */
*again = FALSE;
@ -2079,11 +2030,6 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
goto error_return;
}
/* Compute the TLS segment information. The version normally found in
elf_hash_table (link_info)->tls_segment isn't built until final_link.
??? Probably should look into extracting this into a common function. */
info.tls_segment = elf64_alpha_relax_find_tls_segment (&info, &tls_segment);
for (irel = internal_relocs; irel < irelend; irel++)
{
bfd_vma symval;
@ -2137,7 +2083,7 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
if (r_type == R_ALPHA_TLSLDM)
{
info.tsec = bfd_abs_section_ptr;
symval = alpha_get_tprel_base (info.tls_segment);
symval = alpha_get_tprel_base (info.link_info);
}
else
{
@ -4294,7 +4240,6 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
struct elf_link_tls_segment *tls_segment;
asection *sgot, *srel, *srelgot;
bfd *dynobj, *gotobj;
bfd_vma gp, tp_base, dtp_base;
@ -4348,11 +4293,10 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
local_got_entries = alpha_elf_tdata(input_bfd)->local_got_entries;
tls_segment = elf_hash_table (info)->tls_segment;
if (tls_segment)
if (elf_hash_table (info)->tls_sec != NULL)
{
dtp_base = alpha_get_dtprel_base (tls_segment);
tp_base = alpha_get_tprel_base (tls_segment);
dtp_base = alpha_get_dtprel_base (info);
tp_base = alpha_get_tprel_base (info);
}
else
dtp_base = tp_base = 0;
@ -4674,13 +4618,13 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
}
else if (r_type == R_ALPHA_DTPREL64)
{
BFD_ASSERT(tls_segment != NULL);
BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
value -= dtp_base;
goto default_reloc;
}
else if (r_type == R_ALPHA_TPREL64)
{
BFD_ASSERT(tls_segment != NULL);
BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
if (!info->shared)
{
value -= tp_base;
@ -4760,7 +4704,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
value = 0;
else
{
BFD_ASSERT(tls_segment != NULL);
BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
value -= dtp_base;
}
bfd_put_64 (output_bfd, value,
@ -4783,7 +4727,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
bfd_archive_filename (input_bfd), h->root.root.root.string);
ret_val = FALSE;
}
BFD_ASSERT(tls_segment != NULL);
BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
value -= dtp_base;
if (r_type == R_ALPHA_DTPRELHI)
value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
@ -4806,7 +4750,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
bfd_archive_filename (input_bfd), h->root.root.root.string);
ret_val = FALSE;
}
BFD_ASSERT(tls_segment != NULL);
BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
value -= tp_base;
if (r_type == R_ALPHA_TPRELHI)
value = ((bfd_signed_vma) value >> 16) + ((value >> 15) & 1);
@ -4827,7 +4771,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
value = 0;
else
{
BFD_ASSERT(tls_segment != NULL);
BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
if (r_type == R_ALPHA_GOTDTPREL)
value -= dtp_base;
else if (!info->shared)

View File

@ -2837,9 +2837,6 @@ struct ppc_link_hash_table
asection *brlt;
asection *relbrlt;
/* Short-cut to first output tls section. */
asection *tls_sec;
/* Shortcut to .__tls_get_addr. */
struct elf_link_hash_entry *tls_get_addr;
@ -5172,22 +5169,14 @@ ppc64_elf_edit_opd (bfd *obfd, struct bfd_link_info *info)
return TRUE;
}
/* Set htab->tls_sec. */
/* Set htab->tls_get_addr and call the generic ELF tls_setup function. */
bfd_boolean
asection *
ppc64_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
{
asection *tls;
struct ppc_link_hash_table *htab;
for (tls = obfd->sections; tls != NULL; tls = tls->next)
if ((tls->flags & (SEC_THREAD_LOCAL | SEC_LOAD))
== (SEC_THREAD_LOCAL | SEC_LOAD))
break;
htab = ppc_hash_table (info);
htab->tls_sec = tls;
if (htab->tls_get_addr != NULL)
{
struct elf_link_hash_entry *h = htab->tls_get_addr;
@ -5199,7 +5188,7 @@ ppc64_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
htab->tls_get_addr = h;
}
return tls != NULL;
return _bfd_elf_tls_setup (obfd, info);
}
/* Run through all the TLS relocs looking for optimization
@ -5282,7 +5271,7 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
is_local = TRUE;
value += sym_sec->output_offset;
value += sym_sec->output_section->vma;
value -= htab->tls_sec->vma;
value -= htab->elf.tls_sec->vma;
ok_tprel = (value + TP_OFFSET + ((bfd_vma) 1 << 31)
< (bfd_vma) 1 << 32);
}
@ -7690,8 +7679,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
{
/* Was an LD reloc. */
r_symndx = 0;
rel->r_addend = htab->tls_sec->vma + DTP_OFFSET;
rel[1].r_addend = htab->tls_sec->vma + DTP_OFFSET;
rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
rel[1].r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
}
else if (toc_symndx != 0)
r_symndx = toc_symndx;
@ -8096,7 +8085,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
{
outrel.r_addend += relocation;
if (tls_type & (TLS_GD | TLS_DTPREL | TLS_TPREL))
outrel.r_addend -= htab->tls_sec->vma;
outrel.r_addend -= htab->elf.tls_sec->vma;
}
loc = relgot->contents;
loc += (relgot->reloc_count++
@ -8113,7 +8102,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
relocation = 1;
else if (tls_type != 0)
{
relocation -= htab->tls_sec->vma + DTP_OFFSET;
relocation -= htab->elf.tls_sec->vma + DTP_OFFSET;
if (tls_type == (TLS_TLS | TLS_TPREL))
relocation += DTP_OFFSET - TP_OFFSET;
@ -8223,7 +8212,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
case R_PPC64_TPREL16_HIGHERA:
case R_PPC64_TPREL16_HIGHEST:
case R_PPC64_TPREL16_HIGHESTA:
addend -= htab->tls_sec->vma + TP_OFFSET;
addend -= htab->elf.tls_sec->vma + TP_OFFSET;
if (info->shared)
/* The TPREL16 relocs shouldn't really be used in shared
libs as they will result in DT_TEXTREL being set, but
@ -8241,7 +8230,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
case R_PPC64_DTPREL16_HIGHERA:
case R_PPC64_DTPREL16_HIGHEST:
case R_PPC64_DTPREL16_HIGHESTA:
addend -= htab->tls_sec->vma + DTP_OFFSET;
addend -= htab->elf.tls_sec->vma + DTP_OFFSET;
break;
case R_PPC64_DTPMOD64:
@ -8250,11 +8239,11 @@ ppc64_elf_relocate_section (bfd *output_bfd,
goto dodyn;
case R_PPC64_TPREL64:
addend -= htab->tls_sec->vma + TP_OFFSET;
addend -= htab->elf.tls_sec->vma + TP_OFFSET;
goto dodyn;
case R_PPC64_DTPREL64:
addend -= htab->tls_sec->vma + DTP_OFFSET;
addend -= htab->elf.tls_sec->vma + DTP_OFFSET;
/* Fall thru */
/* Relocations that may need to be propagated if this is a

View File

@ -23,7 +23,7 @@ bfd_boolean ppc64_elf_mark_entry_syms
(struct bfd_link_info *);
bfd_boolean ppc64_elf_edit_opd
(bfd *, struct bfd_link_info *);
bfd_boolean ppc64_elf_tls_setup
asection *ppc64_elf_tls_setup
(bfd *, struct bfd_link_info *);
bfd_boolean ppc64_elf_tls_optimize
(bfd *, struct bfd_link_info *);

View File

@ -2186,10 +2186,10 @@ static bfd_vma
dtpoff_base (info)
struct bfd_link_info *info;
{
/* If tls_segment is NULL, we should have signalled an error already. */
if (elf_hash_table (info)->tls_segment == NULL)
/* If tls_sec is NULL, we should have signalled an error already. */
if (elf_hash_table (info)->tls_sec == NULL)
return 0;
return elf_hash_table (info)->tls_segment->start;
return elf_hash_table (info)->tls_sec->vma;
}
/* Return the relocation value for @tpoff relocation
@ -2200,14 +2200,12 @@ tpoff (info, address)
struct bfd_link_info *info;
bfd_vma address;
{
struct elf_link_tls_segment *tls_segment
= elf_hash_table (info)->tls_segment;
struct elf_link_hash_table *htab = elf_hash_table (info);
/* If tls_segment is NULL, we should have signalled an error already. */
if (tls_segment == NULL)
/* If tls_sec is NULL, we should have signalled an error already. */
if (htab->tls_sec == NULL)
return 0;
return (align_power (tls_segment->size, tls_segment->align)
+ tls_segment->start - address);
return htab->tls_size + htab->tls_sec->vma - address;
}
/* Complain if TLS instruction relocation is against an invalid

View File

@ -1739,10 +1739,10 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
static bfd_vma
dtpoff_base (struct bfd_link_info *info)
{
/* If tls_segment is NULL, we should have signalled an error already. */
if (elf_hash_table (info)->tls_segment == NULL)
/* If tls_sec is NULL, we should have signalled an error already. */
if (elf_hash_table (info)->tls_sec == NULL)
return 0;
return elf_hash_table (info)->tls_segment->start;
return elf_hash_table (info)->tls_sec->vma;
}
/* Return the relocation value for @tpoff relocation
@ -1751,14 +1751,12 @@ dtpoff_base (struct bfd_link_info *info)
static bfd_vma
tpoff (struct bfd_link_info *info, bfd_vma address)
{
struct elf_link_tls_segment *tls_segment
= elf_hash_table (info)->tls_segment;
struct elf_link_hash_table *htab = elf_hash_table (info);
/* If tls_segment is NULL, we should have signalled an error already. */
if (tls_segment == NULL)
if (htab->tls_sec == NULL)
return 0;
return address - align_power (tls_segment->size, tls_segment->align)
- tls_segment->start;
return address - htab->tls_size - htab->tls_sec->vma;
}
/* Relocate an x86_64 ELF section. */

View File

@ -2519,3 +2519,31 @@ _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h,
dynamic linker will resolve them locally. */
return local_protected;
}
/* Caches some TLS segment info, and ensures that the TLS segment vma is
aligned. Returns the first TLS output section. */
struct bfd_section *
_bfd_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
{
struct bfd_section *sec, *tls;
unsigned int align = 0;
for (sec = obfd->sections; sec != NULL; sec = sec->next)
if ((sec->flags & SEC_THREAD_LOCAL) != 0)
break;
tls = sec;
for (; sec != NULL && (sec->flags & SEC_THREAD_LOCAL) != 0; sec = sec->next)
if (sec->alignment_power > align)
align = sec->alignment_power;
elf_hash_table (info)->tls_sec = tls;
/* Ensure the alignment of the first section is the largest alignment,
so that the tls segment starts aligned. */
if (tls != NULL)
tls->alignment_power = align;
return tls;
}

View File

@ -2804,8 +2804,6 @@ 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. */
@ -3160,14 +3158,6 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
finfo.symshndxbuf = NULL;
finfo.symbuf_count = 0;
finfo.shndxbuf_size = 0;
finfo.first_tls_sec = NULL;
for (o = abfd->sections; o != 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
@ -3525,38 +3515,30 @@ elf_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
goto error_return;
}
if (finfo.first_tls_sec)
if (elf_hash_table (info)->tls_sec)
{
unsigned int align = 0;
bfd_vma base = finfo.first_tls_sec->vma, end = 0;
bfd_vma base, end = 0;
asection *sec;
for (sec = finfo.first_tls_sec;
for (sec = elf_hash_table (info)->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)
if (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;
base = elf_hash_table (info)->tls_sec->vma;
end = align_power (end, elf_hash_table (info)->tls_sec->alignment_power);
elf_hash_table (info)->tls_size = end - base;
}
/* Since ELF permits relocations to be against local symbols, we
@ -4503,8 +4485,8 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
{
/* 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;
BFD_ASSERT (elf_hash_table (finfo->info)->tls_sec != NULL);
sym.st_value -= elf_hash_table (finfo->info)->tls_sec->vma;
}
}
}
@ -4862,8 +4844,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
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;
BFD_ASSERT (elf_hash_table (finfo->info)->tls_sec != NULL);
osym.st_value -= elf_hash_table (finfo->info)->tls_sec->vma;
}
}
@ -5219,8 +5201,10 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
{
/* 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;
BFD_ASSERT (elf_hash_table (finfo->info)
->tls_sec != NULL);
sym.st_value -= (elf_hash_table (finfo->info)
->tls_sec->vma);
}
}

View File

@ -3544,12 +3544,10 @@ 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;
asection *tls_sec = elf_hash_table (info)->tls_sec;
BFD_ASSERT (tls_segment != NULL);
return (tls_segment->start
- align_power ((bfd_vma) 16, tls_segment->align));
BFD_ASSERT (tls_sec != NULL);
return tls_sec->vma - align_power ((bfd_vma) 16, tls_sec->alignment_power);
}
/* Return the base VMA address which should be subtracted from real addresses
@ -3560,8 +3558,8 @@ 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;
BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
return elf_hash_table (info)->tls_sec->vma;
}
/* Called through qsort to sort the .IA_64.unwind section during a

View File

@ -1,3 +1,8 @@
2003-11-04 Alan Modra <amodra@bigpond.net.au>
* emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation): Call
_bfd_elf_tls_setup.
2003-10-31 Nick Clifton <nickc@redhat.com>
* ldlang.c (lookup_name): When looking for a previously loaded

View File

@ -845,6 +845,9 @@ gld${EMULATION_NAME}_before_allocation (void)
const char *rpath;
asection *sinterp;
if (link_info.hash->creator->flavour == bfd_target_elf_flavour)
_bfd_elf_tls_setup (output_bfd, &link_info);
/* If we are going to make any variable assignments, we need to let
the ELF backend know about them in case the variables are
referred to by dynamic objects. */