public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* RFC: TLS improvements for IA32 and AMD64/EM64T
@ 2005-09-16  6:07 Alexandre Oliva
  2005-09-16  7:27 ` Alexandre Oliva
  0 siblings, 1 reply; 17+ messages in thread
From: Alexandre Oliva @ 2005-09-16  6:07 UTC (permalink / raw)
  To: binutils, gcc, libc-alpha

[-- Attachment #1: Type: text/plain, Size: 542 bytes --]

Over the past few months, I've been working on porting to IA32 and
AMD64/EM64T the interesting bits of the TLS design I came up with for
FR-V, achieving some impressive speedups along with slight code size
reductions in the most common cases.

Although the design is not set in stone yet, it's fully implemented
and functional with patches I'm about to post for binutils, gcc and
glibc mainline, as follow-ups to this message, except that the GCC
patch will go to gcc-patches, as expected.

The specs RFC is attached.  Comments are welcome.


[-- Attachment #2: RFC-TLSDESC-x86.txt --]
[-- Type: text/plain, Size: 26757 bytes --]

	Thread Local Storage Descriptors for IA32 and AMD64/EM64T

		      Version 0.9.2 - 2005-09-15

     Alexandre Oliva <aoliva@redhat.com, oliva@lsd.ic.unicamp.br>


Introduction
============

While porting NPTL to the FR-V architecture, an idea occurred to me
that would enable significant improvements to the General Dynamic and
Local Dynamic access models to thread-local variables.  These methods
are known to be extremely inefficient because of the need to call a
function to obtain the address of a thread-local variable, a function
that can often be quite inefficient.

The reason for calling such a function is that, when code is compiled
for a dynamic library (the cases in which these access models are
used), it is not generally possible to know whether a thread-local
variable is going to be allocated in the Static Thread Local Storage
Block or not.  Dynamic libraries that are loaded at program start up
can have their thread local storage sections assigned to this static
block, since their TLS requirements are all known before the program
is initiated.  Libraries loaded at a later time, however, may need
dynamically-allocated storage for their TLS blocks.

In the former case, the offset from the Thread Pointer, usually held
in a register, to the thread-local variable is going to be the same
for all threads, whereas in the latter case, such offset may vary, and
it may even be necessary to allocate storage for the variable at the
time it is accessed.

Existing implementations of GD and LD access models did not take
advantage of this run-time constant to speed up the case of libraries
loaded before program start up, a case that is certainly the most
common.

Even though libraries can choose more efficient access models, they
can only do so by giving up the ability for the modules that define
such variables to be loaded after program start up, since different
code sequences have to be generated in this case.

The method proposed here doesn't make a compile-time trade off; it
rather decides, at run time, how each variable can be accessed most
efficiently, without any penalty on code or data sizes in case the
variable is defined in an initially-loaded module, and with some
additional data, allocated dynamically, for the case of late-loaded
modules.  In both cases, performance is improved over the traditional
access models.

Another advantage of this novel design for such access models is that
it enables relocations to thread-local variables to be resolved
lazily.


Background
==========

Thread-local storage is organized as follows: for every thread, two
blocks of memory are allocated: a Static TLS block and a Dynamic
Thread Vector.  A thread pointer, normally a reserved register, points
to some fixed location in the Static TLS block, that contains a
pointer to the dynamic thread vector at some fixed location as well.

TLS for the main executable, if it has a TLS section, is also at a
fixed offset from the thread pointer.  Other modules loaded before the
program starts will also have their TLS sections assigned to the
Static TLS block.

The dynamic thread vector starts with a generation count, followed by
pointers to TLS blocks holding thread-specific copies of the TLS
sections of each module.

If modules are loaded at run time, the dynamic thread vector may need
to grow, and the corresponding TLS blocks may have to be allocated
dynamically.  The generation count is used to control whether the DTV
is up-to-date with regard to newly-loaded or unloaded modules,
enabling the reuse of entries without confusion on whether a TLS block
has been created and initialized for a newly-loaded module or whether
that block was used by a module already unloaded, that is still
waiting for deallocation.


Programs can access thread-local variables by using code that follows
4 different models: Local Exec, Initial Exec, General Dynamic and
Local Dynamic.

Local Exec is only applicable when code in the main executable
accesses a thread-local variable also defined in the main executable.
In such cases, the offset from the Thread Pointer to the variable can
be computed by the linker, so the access model consists in simply
adding this offset to the Thread Pointer to compute the address of the
variable.

Initial Exec is applicable when code in the main executable accesses
thread-local variables that are defined in other loadable modules that
are dependencies of this executable.  Since the dynamic loader will
make sure they are loaded before the program can start running, it can
lay out the Static TLS Block taking their TLS sections' sizes and
alignment requirements into account.  Since the Thread Pointer points
into the same location within the Static TLS Block of each thread, the
offset from the Thread Pointer to the variable one wants to access is
constant for all threads.  However, unlike the Local Exec case, it is
not known at link time, but rather at run time.  So, the compiler
arranges for the offset to be loaded from a Global Offset Table entry,
that the linker creates to hold the TP offset of the variable, and
adds that to the TP to access the variable.  The linker also emits a
dynamic relocation for the dynamic loader to fill in the GOT entry
with the correct value.

Although the Initial Exec access model is intended for use in code
generated for executables, some dynamic libraries may use it as well,
when they know the referenced variable is defined in the main
executable or in another initially-loaded dynamic library.  In fact,
if a dynamic library references a thread-local variable defined in
itself, using the Initial Exec access model, it may be giving up the
ability to be loaded at run time, with mechanisms such as the dlopen()
library call.


General Dynamic is the most general access model, in that it poses no
requirement whatsoever on the variable-accessing or the
variable-defining modules.  This access model has traditionally
involved calling a function, typically called __tls_get_addr(), to
obtain the address of a thread-local variable.  This function takes
two pieces of information to compute the address: a module id, an
index into the dynamic thread vector corresponding to the module in
which the variable is defined, and an offset of the variable from the
beginning of the corresponding TLS block.

These two pieces of information are computed by the dynamic loader, in
GOT locations determined by the linker.  If they're adjacent, it's
possible to pass both pieces of information to __tls_get_addr() by
means of a single pointer; otherwise, they're usually passed as two
separate arguments.  In either case, the code sets up arguments for
__tls_get_addr() and then calls it explicitly, using the returned
value as the address of the variable.

The Local Dynamic access model can only be used to access variables
that are local to the module in which they're used, and it only makes
sense when accessing multiple such variables.  The idea is to use a
single call to __tls_get_addr() to compute the base address of the TLS
block for the module.  Then, to access variables, it suffices to add
to this base address the offset corresponding to each variable.  The
offset can be used as a literal in the code, since it's determined by
the linker when it lays out the TLS section of the module.


Overall Design
==============

The optimization proposed herein intends to improve the performance of
dynamic libraries that access thread-local variables using the dynamic
access models, in cases they're loaded before program start up,
without slowing down (or, if possible, speeding up) the performance
when the same libraries are loaded during run time.

The idea is to use TLS descriptors containing a pointer to a function
and an argument.  This uses two words in the GOT, just like the
arguments traditionally passed to __tls_get_addr(), but uses this
space in a very different way.

A single relocation is to be used to compute the value of the two
words of the TLS descriptor.  The dynamic loader, when resolving the
relocation, can determine whether the TLS block used for the module
that defines the TLS symbol is in the static TLS block or not.

If it is in the static TLS block, the offset from the TP to the symbol
is constant for all threads, so it sets the argument in the TLS
descriptor to this constant offset, and sets the function pointer to a
piece of code that simply returns the argument (plus the TP, in an
alternate design).

If the defining module is in dynamically-allocated TLS, it sets the
argument to a dynamically-allocated extended descriptor containing the
arguments passed to __tls_get_addr() and the module's generation
count, and the function pointer to a piece of code that checks whether
the generation count is sufficiently up to date and that the DTV entry
is set.  If so, this piece of code loads the DTV entry, adds the
symbol offset to it, and subtracts the TP value (unless using the
alternate design), returning the result.  Otherwise, it calls
__tls_get_addr(), and subtracts from its return value the TP (unless
using the alternate design).

The functions defined above use custom calling conventions that
require them to preserve any registers they modify.  This penalizes
the case that requires dynamic TLS, since it must preserve all
call-clobbered registers before calling __tls_get_addr(), but it is
optimized for the most common case of static TLS, and also for the
case in which the code generated by the compiler can be relaxed by the
linker to a more efficient access model: being able to assume no
registers are clobbered by the call tends to improve register
allocation.  Also, the function that handles the dynamic TLS case will
most often be able to avoid calling __tls_get_addr(), thus potentially
avoiding the need for preserving registers.


Lazy relocation is accomplished by setting the argument portion of the
TLS descriptor to point to the relocation, and the function pointer to
point to a lazy relocation function.  Some effort is needed to ensure
that the TLS descriptor is modified and accessed atomically, and that
the lazy relocation function can quickly identify the module that
contains the relocation.


This optimized access model thus consists in setting up a pointer to
the TLS descriptor (or, in another alternate design, loading its
contents atomically), then calling the function at the address given
by the pointer to function in the TLS descriptor, passing to it a
pointer to the descriptor itself (or, in an alternate design, the
argument portion of the TLS descriptor).  The value returned by this
call can then be used as an offset from the thread pointer to access
the variable (or as the address of the variable, in the first
alternate design).

The actual code sequences and implementation details for IA32 and
AMD64/EM64T are depicted in the following subsections.


IA32
----

The general dynamic access model used to be:

        leal    variable@TLSGD(,%ebx,1), %eax
        call    ___tls_get_addr@PLT
	# use %eax as the address, or (%eax) to access the value

After the call instruction, %eax holds the address of variable.
variable@TLSGD is resolved by the linker to the GOT offset holding the
data structure passed by reference to ___tls_get_addr(), containing
the TLS module id and the TLS offset, computed by two separate dynamic
relocations.  The odd addressing mode is needed to make the
instruction longer, such that, in case the linker finds out it can
relax the code sequence, the necessary code fits.


The optimized method proposed here uses:

        leal    tval@TLSDESC(%ebx), %eax
	[...] # any other instructions that preserve %eax
        call    *tval@TLSCALL(%eax)
	# add %gs:0 to %eax to compute the address,
	# or use %gs:(%eax) to access the value

Note that this call instruction is actually emitted without an offset,
so it's 4 bytes shorter than it appears to be.  It's equivalent to
`call *(%eax)', that emits a two-byte instruction, but it's annotated
with a relocation that enables the leal and the call to be moved apart
from each other, for better scheduling.  The following new relocations
types are used by the code above:

#define R_386_TLS_GOTDESC  38		/* GOT offset for TLS descriptor.  */
#define R_386_TLS_DESC     39		/* TLS descriptor containing
					   pointer to code and to
					   argument, returning the TLS
					   offset for the symbol.  */
#define R_386_TLS_DESC_CALL 40		/* Marker of call through TLS
					   descriptor for
					   relaxation.  */

TLS_DESC is the dynamic relocation that the linker emits in response
to the two other relocations.  All of the relocations accept addends;
being REL, the relocations have in-place addends.  In the TLS_DESC
case, that applies to a pair of words, the addend is stored in the
second word, to simplify some lazy relocation cases.  In order to
enable lazy relocation, %ebx MUST point to the GOT at the point of the
call instruction.

Instead of adding more relocations for the Local Dynamic case, we
propose the use a symbol _TLS_MODULE_BASE_, that the linker implicitly
defines, as a hidden symbol, to the base address of the TLS section of
a module.


When relaxing the sequence above to the Initial Exec model, we'd get
sequences such as:

	movl	variable@GOTNTPOFF(%ebx), %eax
	[...]
	movl	%eax, %eax	   # or any other two-byte nop

or:

	leal	variable@GOTNTPOFF(%ebx), %eax
	[...]
	movl	(%eax), %eax

or, in case there's a GOT entry holding the positive TPOFF:

	movl	variable@GOTTPOFF(%ebx), %eax
	[...]
	negl	%eax

I'm not sure which of these would be better to use, but in my current
implementation I've preferred the first alternative, unless a GOT
entry for the third is needed for other reasons, and one for the
first case isn't.


The Local Exec model uses code such as:

	.byte 0x65	       # %gs, or any harmless 1-byte prefix
	movl	$variable@NTPOFF, %eax
	[...]
	movl	%eax, %eax	# or any other two-byte nop

or:

	leal	variable@NTPOFF, %eax	# avoiding the need for the prefix
	[...]
	movl	%eax, %eax	# or any other two-byte nop


The function for the static TLS case can be as simple as:

_dl_tlsdesc_return:
	movl	4(%eax), %eax
	ret

whereas the other takes a bit more effort, requiring the following
data structure definitions:

struct tlsdesc
{
  ptrdiff_t __attribute__((regparm(1))) (*entry)(struct tlsdesc *);
  void *arg;
};

typedef struct dl_tls_index
{
  unsigned long int ti_module;
  unsigned long int ti_offset;
} tls_index;

struct tlsdesc_dynamic_arg
{
  tls_index tlsinfo;
  size_t gen_count;
};

The definition of the resolution function follows the logic depicted
below, except for the need to preserve all registers except %eax.

ptrdiff_t
__attribute__ ((__regparm__ (1)))
_dl_tlsdesc_dynamic (struct tlsdesc *tdp) 
{
  struct tlsdesc_dynamic_arg *td = tdp->arg; 
  dtv_t *dtv = *(dtv_t **)((char *)__thread_pointer + DTV_OFFSET);
  if (__builtin_expect (td->gen_count <= dtv[0].counter
			&& (dtv[td->tlsinfo.ti_module].pointer.val
			    != TLS_DTV_UNALLOCATED),
			1))
    return dtv[td->tlsinfo.ti_module].pointer.val + td->tlsinfo.ti_offset 
      - __thread_pointer;

  /* Preserve any call-clobbered registers not preserved because of
     the above across the call below.  */
  return ___tls_get_addr (&td->tlsinfo) - __thread_pointer;
}

The tlsdesc_dynamic_arg objects are allocated by the dynamic loader
when resolving a relocation, and stored in a hash table created for
the module in which the symbol is defined.  Note that this dynamic
allocation has no implications to prelinking, since prelinking is
only applicable to modules loaded before program start up, and thus
always uses the static TLS case, that does not need dynamic
allocation.


An alternate design in which the function called through the TLS
descriptor returns not the TP offset, but rather the address of the
variable of interest, could refrain from adding %gs:0 to the value
returned by the call to compute the address of a symbol, and from
using the %gs: prefix when accessing the variable, but it would
require the use of a longer call instruction to enable proper
relaxation.  The call instruction would have to be 7, instead of 2
bytes long, such that the linker could relax it to `addl %gs:0, %eax'.
This would make code that accesses the variable 4 bytes longer on
average (5 bytes minus one used by the %gs prefix), whereas code that
computes its address would be shorter by only two bytes.  It's not
clear such a change would be profitable.


Lazy relocation is not profitable in all cases.  Consider that we need
the argument in the TLS descriptor to hold both the addend and the
address of the relocation, if it's a REL relocation, and it probably
wouldn't make sense to depend on dynamic memory allocation for the
relocation.  So, in case we actually need both pieces of information,
we perform the relocation immediately.

In other cases, such as that of RELA relocations and REL relocations
with zero addends, we use the argument to hold a pointer to the
relocation.  Another special case we handle is that of REL relocations
with addends that reference the *ABS* section, i.e., that reference
the local TLS section.

All cases handled by lazy relocation start by grabbing a global
dynamic loader lock and checking that the pointer in the TLS
descriptor hasn't changed.  If it has, we return immediately into the
new pointer, after releasing the lock.  Otherwise, we set the function
pointer to a hold function that will get all other threads that
attempt to use this variable to wait until relocation is complete.

After diverting any other threads to the hold function, we can perform
the relocation, determining whether the referenced symbol is in Static
TLS or not, and deciding which of the two functions to use from that
point on and computing the argument to pass to it.  The argument is
stored first in the TLS descriptor, and the new entry point is stored
last.  The relocation functions finally release the lock and return
into the newly-computed function.

In the current implementation, the hold function attempts to grab the
lock, checks that the pointer hasn't changed and releases the lock,
such that, if any other such TLS descriptor lazy relocation is in
progress, it will wait until the lock is released.  When it obtains
the lock, it releases it immediately and returns into the function
newly-stored in the TLS descriptor.

An alternate implementation is envisioned that relies on condition
variables that hold functions would wait on, such that the relocation
functions wouldn't have to hold the lock throughout their execution,
rather waking up all hold functions upon completion of the relocation.


AMD64/EM64T
-----------

The design is very similar to that of IA32.  The main difference stems
from the fact that AMD64's IP-relative addressing modes have enabled
it to do away with the need for a register holding the GOT pointer,
which in turn required additional measures to enable lazy relocation
of TLS descriptors.

Where the existing ABI uses the following sequence:

        .byte   0x66
        leaq    variable@TLSGD(%rip), %rdi
        .word   0x6666
        rex64
        call    __tls_get_addr@PLT
	# use %eax as the address, or (%eax) to access the value

we propose this instead:

        leaq    tval@TLSDESC(%rip), %rax
	[...] # any other instructions that preserve %eax
        call    *tval@TLSCALL(%rax)
	# add %fs:0 to %eax to compute the address,
	# or use %fs:(%eax) to access the value

Note that, as in the IA32 case, the call instruction is a two-byte
instruction, the offset is completely discarded by the assembler.  The
following new relocations types are used by the code above:

#define R_X86_64_GOTPC32_TLSDESC 27	/* GOT offset for TLS descriptor.  */
#define R_X86_64_TLSDESC         28	/* TLS descriptor.  */
#define R_X86_64_TLSDESC_CALL    29	/* Marker for call through TLS
					   descriptor.  */

As on IA32, _TLS_MODULE_BASE_ is to be used to obtain the base address
for the Local Dynamic access model.


The alternate design proposed for IA32 that gets the TLS descriptor
call to compute not the offset, but the actual address of the
variable, would require a much longer call instruction to accommodate
the 9 bytes needed to add the TP to the address in case of
relaxation, so it is even less likely to be profitable.


When relaxing the sequence above to the Initial Exec model, we'd get
sequences such as:

        movq    variable@GOTTPOFF(%rip), %rax
	[...]
        rex64 nop	   # or any other two-byte nop

I'm not sure this last instruction is the most efficient 2-bytes-long
do-nothing instruction available on AMD64, but it's used for Local
Exec as well:

        movq    $variable@TPOFF, %rax
	[...]
        rex64 nop


The other data structures and TLS descriptor offset computation
functions are equivalent to those used on IA32, with one point worth
noting that the type of the `entry' member of struct tlsdesc cannot be
represented in C, and not even in GNU-extended C, since the function
takes its argument in %rax, rather than in %rdi.


Since AMD64 uses RELA dynamic relocations, all TLS descriptors are
suitable for lazy relocation; there's no need to worry about
preserving the addend, since it is held in the relocation table
itself.  Thus, there's only need for one lazy relocation function.

That said, this function needs some means to be told what module the
relocation at hand refers to.  On IA32, this is done by means of the
reserved register %ebx, that points to the Global Offset Table, but no
register holds this pointer on AMD64.  Although it would be possible
to use the relocation pointer to search the relocation ranges for all
loaded modules, this would be extremely inefficient, so we've
introduced two dynamic table entries to enable the dynamic loader to
communicate with modules that use lazy relocation:

#define DT_TLSDESC_GOT	0x6ffffff7	/* Location of GOT entry used
					   by TLS descriptor resolver
					   PLT entry.  */
#define DT_TLSDESC_PLT	0x6ffffff8	/* Location of PLT entry for
					   TLS descriptor resolver
					   calls.  */

A module that uses lazy TLSDESC relocations MUST define these two
entries.  The former indicates the address of a GOT entry to be filled
in by the dynamic loader with the address of the internal function to
be used for lazy relocation of TLS descriptors.  The latter must hold
the address of a PLT entry that pushes onto the stack the module's
link map address, located in the GOT portion reserved for the dynamic
loader to use, and then jumps to the lazy relocation function, using
the address stored in the TLSDESC_GOT entry.  The lazy relocation
function is responsible for releasing the stack slot taken up by the
PLT entry.


Future Improvements
===================

The use of TLS descriptors to access thread-local variables would
enable the compression of the DTV such that it contained only entries
for non-static modules.  Static ones could be given negative ids, such
that legacy relocations and direct calls to __tls_get_addr() could
still work correctly, but entries could be omitted from the DTV, and
the DTV entries would no longer need the boolean currently used to
denote entries that are in Static TLS.

The DTV could also be modified so as to contain TP offsets instead of
absolute addresses.  Some refactoring of _dl_tlsdesc_dynamic() and
__tls_get_addr() could avoid the need to subtract TP in the former,
using an alternate entry point that refrains from adding the TP to the
offsets in the new DTV.

It might make sense to combine the current design, in which TLSCALL
functions return the TP offsets, with the alternate design in which
they return the actual address, introducing different relocations for
each case, enabling code to use the former when accessing variables
directly using the TP segment register, and using the latter when
computing their addresses.  It's not obvious that this would have any
significant impact on performance, and although code size could
certainly be reduced for code that computes the address of
thread-local variables, it's not obvious that the need for additional
GOT entries and supporting code would not make up for it.


Conclusion
==========

The design described above is currently functional, using CVS
snapshots of GCC, binutils and glibc taken today, plus local changes
about to be contributed.

Even though the performance of the standard NPTL benchmark is improved
by only a negligible margin, that's understandable: glibc and nptl,
aware that the dynamic access models used to be so inefficient, take
advantage of the fact that libc is always loaded initially and
reference almost all thread-local variables using the more efficient
access models.

However, synthetic benchmarks designed to time functions that return
the value or the address of thread-local variables, have shown that
the performance of the proposed method is significantly better than
that of the currently-used method.  When the referenced variable is
found to be in static TLS at run time, the newly-proposed method makes
such functions about twice as fast as when using the method in wide
use today, bringing it close to the performance of the Initial Exec
model.  Even when the variable is in dynamic TLS, the speedup is still
over 20%.

As for code size, the new method tends to be a win for dynamic
libraries that access TLS variables through the segment registers more
often than they compute the address of such variables.  Libraries in
GNU libc such as libpthread, libmemusage, as well as most dynamic
libraries used in its testsuite, have experienced small reductions in
code size on both architectures.  The dynamic loader and libm
experienced size reductions only on AMD64, retaining the same size on
IA32.  Only libc itself grew in terms of code size, and only on AMD64,
by as little as 0.014%.


This is a draft of work in progress.  The ABI changes suggested above
are not to be taken as final.  In particular, the relocation numbers
and dynamic table entries have not been approved by the official
maintainers of the ABIs, the instruction selection is still subject to
change and even the calling conventions may be modified without
notice.

Copyright 2005 Alexandre Oliva.  Permission is granted to distribute
verbatim copies of this document.  Please contact the author at
aoliva@redhat.com or oliva@lsd.ic.unicamp.br to request additional
permissions.


Change Log
==========

0.9.2 - 2005-09-15: Rename main section to Overall Design.  Clarify
    how the dynamic TLS handler can often avoid the overhead of
    preserving registers.  Add rough figures of performance
    improvements.

0.9.1 - 2005-09-13: Fixed typos and thinkos.  Improved readability.
    Added section with Future Improvements.

0.9 - 2005-09-09: initial version.

[-- Attachment #3: Type: text/plain, Size: 188 bytes --]


-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: RFC: TLS improvements for IA32 and AMD64/EM64T
  2005-09-16  6:07 RFC: TLS improvements for IA32 and AMD64/EM64T Alexandre Oliva
@ 2005-09-16  7:27 ` Alexandre Oliva
  2005-09-16  7:34   ` Andreas Jaeger
  2005-09-18 17:17   ` Alexandre Oliva
  0 siblings, 2 replies; 17+ messages in thread
From: Alexandre Oliva @ 2005-09-16  7:27 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 1723 bytes --]

On Sep 16, 2005, Alexandre Oliva <aoliva@redhat.com> wrote:

> Over the past few months, I've been working on porting to IA32 and
> AMD64/EM64T the interesting bits of the TLS design I came up with for
> FR-V, achieving some impressive speedups along with slight code size
> reductions in the most common cases.

> Although the design is not set in stone yet, it's fully implemented
> and functional with patches I'm about to post for binutils, gcc and
> glibc mainline, as follow-ups to this message, except that the GCC
> patch will go to gcc-patches, as expected.

Here's the patch for binutils.

I'm not entirely happy with two aspects of the patch:

- the way I managed to emit the `call *(%[er]ax)' instruction from
  `call *variable@TLSCALL(%[er]ax)', dropping the offset from the
  instruction but still emitting the relocation, seems fragile to me,
  but there were not additional bits available to do something
  cleaner.  Any suggestions on a better approach?

- local_tlsdesc_gotent is probably too wasteful, since very few of all
  local symbols are going to require TLS descriptor entries.  I hope
  this is not too much of a problem, but I could introduce another
  data structure if people feel strongly about it.


Also note the several FIXMEs with decisions yet to be made on exact
instructions to be generated in several cases.  I'm yet to develop
some means to better evaluate the performance of each alternative, but
even then, I have limited hardware to test on.  I'd welcome feedback
from people more familiar with performance features of various
x86-compatible processors.  Anyone?  Thanks in advance,

Here's the patch.  Built and tested on x86_64-linux-gnu and
i686-pc-linux-gnu.  Ok to install?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: binutils-20050915.patch --]
[-- Type: text/x-patch, Size: 201411 bytes --]

Index: include/elf/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Introduce TLS descriptors for i386 and x86_64.
	* common.h (DT_TLSDESC_GOT, DT_TLSDESC_PLT): New.
	* i386.h (R_386_TLS_GOTDESC, R_386_TLS_DESC, R_386_TLS_DESC_CALL):
	New.
	* x86-64.h (R_X86_64_GOTPC32_TLSDESC, R_X86_64_TLSDESC,
	R_X86_64_TLSDESC_CALL): New.

Index: include/elf/common.h
===================================================================
RCS file: /cvs/uberbaum/./include/elf/common.h,v
retrieving revision 1.72
diff -u -p -r1.72 common.h
--- include/elf/common.h 14 Jul 2005 22:52:15 -0000 1.72
+++ include/elf/common.h 15 Sep 2005 22:39:19 -0000
@@ -581,6 +581,8 @@
 #define DT_SYMINFO	0x6ffffeff
 #define DT_ADDRRNGHI	0x6ffffeff
 
+#define DT_TLSDESC_GOT	0x6ffffff7
+#define DT_TLSDESC_PLT	0x6ffffff8
 #define DT_RELACOUNT	0x6ffffff9
 #define DT_RELCOUNT	0x6ffffffa
 #define DT_FLAGS_1	0x6ffffffb
Index: include/elf/i386.h
===================================================================
RCS file: /cvs/uberbaum/./include/elf/i386.h,v
retrieving revision 1.10
diff -u -p -r1.10 i386.h
--- include/elf/i386.h 10 May 2005 10:21:10 -0000 1.10
+++ include/elf/i386.h 15 Sep 2005 22:39:19 -0000
@@ -1,5 +1,5 @@
 /* ix86 ELF support for BFD.
-   Copyright 1998, 1999, 2000, 2002, 2004 Free Software Foundation, Inc.
+   Copyright 1998, 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -61,6 +61,9 @@ START_RELOC_NUMBERS (elf_i386_reloc_type
      RELOC_NUMBER (R_386_TLS_DTPMOD32, 35)
      RELOC_NUMBER (R_386_TLS_DTPOFF32, 36)
      RELOC_NUMBER (R_386_TLS_TPOFF32,  37)
+     RELOC_NUMBER (R_386_TLS_GOTDESC,  38)
+     RELOC_NUMBER (R_386_TLS_DESC,     39)
+     RELOC_NUMBER (R_386_TLS_DESC_CALL,40)
 
      /* Used by Intel.  */
      RELOC_NUMBER (R_386_USED_BY_INTEL_200, 200)
Index: include/elf/x86-64.h
===================================================================
RCS file: /cvs/uberbaum/./include/elf/x86-64.h,v
retrieving revision 1.8
diff -u -p -r1.8 x86-64.h
--- include/elf/x86-64.h 25 Jul 2005 15:41:07 -0000 1.8
+++ include/elf/x86-64.h 15 Sep 2005 22:39:19 -0000
@@ -1,5 +1,5 @@
 /* x86_64 ELF support for BFD.
-   Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
    Contributed by Jan Hubicka <jh@suse.cz>
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -53,6 +53,13 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_ty
      RELOC_NUMBER (R_X86_64_GOTOFF64, 25)     /* 64 bit offset to GOT */
      RELOC_NUMBER (R_X86_64_GOTPC32,  26)     /* 32 bit signed pc relative
                                                  offset to GOT */
+     RELOC_NUMBER (R_X86_64_GOTPC32_TLSDESC, 27)
+					      /* 32 bit signed pc relative
+						 offset to TLS descriptor
+						 in the GOT.  */
+     RELOC_NUMBER (R_X86_64_TLSDESC, 28)      /* 2x64-bit TLS descriptor.  */
+     RELOC_NUMBER (R_X86_64_TLSDESC_CALL, 29) /* Relaxable call through TLS
+						 descriptor.  */
      RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250)       /* GNU C++ hack  */
      RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251)         /* GNU C++ hack  */
 END_RELOC_NUMBERS (R_X86_64_max)
Index: bfd/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Introduce TLS descriptors for i386 and x86_64.
	* reloc.c (BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_386_TLS_DESC,
	BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_X86_64_GOTPC32_TLSDESC,
	BFD_RELOC_X86_64_TLSDESC, BFD_RELOC_X86_64_TLSDESC_CALL): New.
	* libbfd.h, bfd-in2.h: Rebuilt.
	* elf32-i386.c (elf_howto_table): New relocations.
	(R_386_tls): Adjust.
	(elf_i386_reloc_type_lookup): Map new relocations.
	(GOT_TLS_GDESC, GOT_TLS_GD_BOTH_P): New macros.
	(GOT_TLS_GD_P, GOT_TLS_GDESC_P, GOT_TLS_GD_ANY_P): New macros.
	(struct elf_i386_link_hash_entry): Add tlsdesc_got field.
	(struct elf_i386_obj_tdata): Add local_tlsdesc_gotent field.
	(elf_i386_local_tlsdesc_gotent): New macro.
	(struct elf_i386_link_hash_table): Add sgotplt_jump_table_size.
	(elf_i386_compute_jump_table_size): New macro.
	(link_hash_newfunc): Initialize tlsdesc_got.
	(elf_i386_link_hash_table_create): Set sgotplt_jump_table_size.
	(elf_i386_tls_transition): Handle R_386_TLS_GOTDESC and
	R_386_TLS_DESC_CALL.
	(elf_i386_check_relocs): Likewise.  Allocate space for
	local_tlsdesc_gotent.
	(elf_i386_gc_sweep_hook): Handle R_386_TLS_GOTDESC and
	R_386_TLS_DESC_CALL.
	(allocate_dynrelocs): Count function PLT relocations.  Reserve
	space for TLS descriptors and relocations.
	(elf_i386_size_dynamic_sections): Reserve space for TLS
	descriptors and relocations.  Set up sgotplt_jump_table_size.
	Don't zero reloc_count in srelplt.
	(elf_i386_always_size_sections): New.  Set up _TLS_MODULE_BASE_.
	(elf_i386_relocate_section): Handle R_386_TLS_GOTDESC and
	R_386_TLS_DESC_CALL.
	(elf_i386_finish_dynamic_symbol): Use GOT_TLS_GD_ANY_P.
	(elf_backend_always_size_sections): Define.
	* elf64-x86-64.c (x86_64_elf_howto): Add R_X86_64_GOTPC32_TLSDESC,
	R_X86_64_TLSDESC, R_X86_64_TLSDESC_CALL.
	(R_X86_64_standard): Adjust.
	(x86_64_reloc_map): Map new relocs.
	(GOT_TLS_GDESC, GOT_TLS_GD_BOTH_P): New macros.
	(GOT_TLS_GD_P, GOT_TLS_GDESC_P, GOT_TLS_GD_ANY_P): New macros.
	(struct elf64_x86_64_link_hash_entry): Add tlsdesc_got field.
	(struct elf64_x86_64_obj_tdata): Add local_tlsdesc_gotent field.
	(elf64_x86_64_local_tlsdesc_gotent): New macro.
	(struct elf64_x86_64_link_hash_table): Add tlsdesc_plt,
	tlsdesc_got and sgotplt_jump_table_size fields.
	(elf64_x86_64_compute_jump_table_size): New macro.
	(link_hash_newfunc): Initialize tlsdesc_got.
	(elf64_x86_64_link_hash_table_create): Initialize new fields.
	(elf64_x86_64_tls_transition): Handle R_X86_64_GOTPC32_TLSDESC and
	R_X86_64_TLSDESC_CALL.
	(elf64_x86_64_check_relocs): Likewise.  Allocate space for
	local_tlsdesc_gotent.
	(elf64_x86_64_gc_sweep_hook): Handle R_X86_64_GOTPC32_TLSDESC and
	R_X86_64_TLSDESC_CALL.
	(allocate_dynrelocs): Count function PLT relocations.  Reserve
	space for TLS descriptors and relocations.
	(elf64_x86_64_size_dynamic_sections): Reserve space for TLS
	descriptors and relocations.  Set up sgotplt_jump_table_size,
	tlsdesc_plt and tlsdesc_got.  Make room for them.  Don't zero
	reloc_count in srelplt.  Add dynamic entries for DT_TLSDESC_PLT
	and DT_TLSDESC_GOT.
	(elf64_x86_64_always_size_sections): New.  Set up
	_TLS_MODULE_BASE_.
	(elf64_x86_64_relocate_section): Handle R_386_TLS_GOTDESC and
	R_386_TLS_DESC_CALL.
	(elf64_x86_64_finish_dynamic_symbol): Use GOT_TLS_GD_ANY_P.
	(elf64_x86_64_finish_dynamic_sections): Set DT_TLSDESC_PLT and
	DT_TLSDESC_GOT.  Set up TLS descriptor lazy resolver PLT entry.
	(elf_backend_always_size_sections): Define.

Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/uberbaum/./bfd/bfd-in2.h,v
retrieving revision 1.366
diff -u -p -r1.366 bfd-in2.h
--- bfd/bfd-in2.h 8 Sep 2005 12:49:18 -0000 1.366
+++ bfd/bfd-in2.h 15 Sep 2005 22:38:15 -0000
@@ -2647,6 +2647,9 @@ in the instruction.  */
   BFD_RELOC_386_TLS_DTPMOD32,
   BFD_RELOC_386_TLS_DTPOFF32,
   BFD_RELOC_386_TLS_TPOFF32,
+  BFD_RELOC_386_TLS_GOTDESC,
+  BFD_RELOC_386_TLS_DESC,
+  BFD_RELOC_386_TLS_DESC_CALL,
 
 /* x86-64/elf relocations  */
   BFD_RELOC_X86_64_GOT32,
@@ -2667,6 +2670,9 @@ in the instruction.  */
   BFD_RELOC_X86_64_TPOFF32,
   BFD_RELOC_X86_64_GOTOFF64,
   BFD_RELOC_X86_64_GOTPC32,
+  BFD_RELOC_X86_64_GOTPC32_TLSDESC,
+  BFD_RELOC_X86_64_TLSDESC,
+  BFD_RELOC_X86_64_TLSDESC_CALL,
 
 /* ns32k relocations  */
   BFD_RELOC_NS32K_IMM_8,
Index: bfd/elf32-i386.c
===================================================================
RCS file: /cvs/uberbaum/./bfd/elf32-i386.c,v
retrieving revision 1.149
diff -u -p -r1.149 elf32-i386.c
--- bfd/elf32-i386.c 31 Aug 2005 23:45:45 -0000 1.149
+++ bfd/elf32-i386.c 15 Sep 2005 22:38:17 -0000
@@ -126,9 +126,18 @@ static reloc_howto_type elf_howto_table[
   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),
+  HOWTO(R_386_TLS_GOTDESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_386_TLS_GOTDESC",
+	TRUE, 0xffffffff, 0xffffffff, FALSE),
+  HOWTO(R_386_TLS_DESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_386_TLS_DESC",
+	TRUE, 0xffffffff, 0xffffffff, FALSE),
+  HOWTO(R_386_TLS_DESC_CALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
+	bfd_elf_generic_reloc, "R_386_TLS_DESC_CALL",
+	FALSE, 0, 0, FALSE),
 
   /* Another gap.  */
-#define R_386_tls (R_386_TLS_TPOFF32 + 1 - R_386_tls_offset)
+#define R_386_tls (R_386_TLS_DESC_CALL + 1 - R_386_tls_offset)
 #define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_tls)
 
 /* GNU extension to record C++ vtable hierarchy.  */
@@ -292,6 +301,18 @@ elf_i386_reloc_type_lookup (bfd *abfd AT
       TRACE ("BFD_RELOC_386_TLS_TPOFF32");
       return &elf_howto_table[R_386_TLS_TPOFF32 - R_386_tls_offset];
 
+    case BFD_RELOC_386_TLS_GOTDESC:
+      TRACE ("BFD_RELOC_386_TLS_GOTDESC");
+      return &elf_howto_table[R_386_TLS_GOTDESC - R_386_tls_offset];
+
+    case BFD_RELOC_386_TLS_DESC:
+      TRACE ("BFD_RELOC_386_TLS_DESC");
+      return &elf_howto_table[R_386_TLS_DESC - R_386_tls_offset];
+
+    case BFD_RELOC_386_TLS_DESC_CALL:
+      TRACE ("BFD_RELOC_386_TLS_DESC_CALL");
+      return &elf_howto_table[R_386_TLS_DESC_CALL - R_386_tls_offset];
+
     case BFD_RELOC_VTABLE_INHERIT:
       TRACE ("BFD_RELOC_VTABLE_INHERIT");
       return &elf_howto_table[R_386_GNU_VTINHERIT - R_386_vt_offset];
@@ -559,7 +580,20 @@ struct elf_i386_link_hash_entry
 #define GOT_TLS_IE_POS	5
 #define GOT_TLS_IE_NEG	6
 #define GOT_TLS_IE_BOTH 7
+#define GOT_TLS_GDESC	8
+#define GOT_TLS_GD_BOTH_P(type)						\
+  ((type) == (GOT_TLS_GD | GOT_TLS_GDESC))
+#define GOT_TLS_GD_P(type)						\
+  ((type) == GOT_TLS_GD || GOT_TLS_GD_BOTH_P (type))
+#define GOT_TLS_GDESC_P(type)						\
+  ((type) == GOT_TLS_GDESC || GOT_TLS_GD_BOTH_P (type))
+#define GOT_TLS_GD_ANY_P(type)						\
+  (GOT_TLS_GD_P (type) || GOT_TLS_GDESC_P (type))
   unsigned char tls_type;
+
+  /* Offset of the GOTPLT entry reserved for the TLS descriptor,
+     starting at the end of the jump table.  */
+  bfd_vma tlsdesc_got;
 };
 
 #define elf_i386_hash_entry(ent) ((struct elf_i386_link_hash_entry *)(ent))
@@ -570,6 +604,9 @@ struct elf_i386_obj_tdata
 
   /* tls_type for each local got entry.  */
   char *local_got_tls_type;
+
+  /* GOTPLT entries for TLS descriptors.  */
+  bfd_vma *local_tlsdesc_gotent;
 };
 
 #define elf_i386_tdata(abfd) \
@@ -578,6 +615,9 @@ struct elf_i386_obj_tdata
 #define elf_i386_local_got_tls_type(abfd) \
   (elf_i386_tdata (abfd)->local_got_tls_type)
 
+#define elf_i386_local_tlsdesc_gotent(abfd) \
+  (elf_i386_tdata (abfd)->local_tlsdesc_gotent)
+
 static bfd_boolean
 elf_i386_mkobject (bfd *abfd)
 {
@@ -620,6 +660,10 @@ struct elf_i386_link_hash_table
     bfd_vma offset;
   } tls_ldm_got;
 
+  /* The amount of space used by the reserved portion of the sgotplt
+     section, plus whatever space is used by the jump slots.  */
+  bfd_vma sgotplt_jump_table_size;
+
   /* Small local sym to section mapping cache.  */
   struct sym_sec_cache sym_sec;
 };
@@ -629,6 +673,9 @@ struct elf_i386_link_hash_table
 #define elf_i386_hash_table(p) \
   ((struct elf_i386_link_hash_table *) ((p)->hash))
 
+#define elf_i386_compute_jump_table_size(htab) \
+  ((htab)->srelplt->reloc_count * 4)
+
 /* Create an entry in an i386 ELF linker hash table.  */
 
 static struct bfd_hash_entry *
@@ -655,6 +702,7 @@ link_hash_newfunc (struct bfd_hash_entry
       eh = (struct elf_i386_link_hash_entry *) entry;
       eh->dyn_relocs = NULL;
       eh->tls_type = GOT_UNKNOWN;
+      eh->tlsdesc_got = (bfd_vma) -1;
     }
 
   return entry;
@@ -686,6 +734,7 @@ elf_i386_link_hash_table_create (bfd *ab
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
   ret->tls_ldm_got.refcount = 0;
+  ret->sgotplt_jump_table_size = 0;
   ret->sym_sec.abfd = NULL;
   ret->is_vxworks = 0;
   ret->srelplt2 = NULL;
@@ -848,6 +897,8 @@ elf_i386_tls_transition (struct bfd_link
   switch (r_type)
     {
     case R_386_TLS_GD:
+    case R_386_TLS_GOTDESC:
+    case R_386_TLS_DESC_CALL:
     case R_386_TLS_IE_32:
       if (is_local)
 	return R_386_TLS_LE_32;
@@ -952,6 +1003,8 @@ elf_i386_check_relocs (bfd *abfd,
 
 	case R_386_GOT32:
 	case R_386_TLS_GD:
+	case R_386_TLS_GOTDESC:
+	case R_386_TLS_DESC_CALL:
 	  /* This symbol requires a global offset table entry.  */
 	  {
 	    int tls_type, old_tls_type;
@@ -961,6 +1014,9 @@ elf_i386_check_relocs (bfd *abfd,
 	      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_GOTDESC:
+	      case R_386_TLS_DESC_CALL:
+		tls_type = GOT_TLS_GDESC; break;
 	      case R_386_TLS_IE_32:
 		if (ELF32_R_TYPE (rel->r_info) == r_type)
 		  tls_type = GOT_TLS_IE_NEG;
@@ -990,13 +1046,16 @@ elf_i386_check_relocs (bfd *abfd,
 		    bfd_size_type size;
 
 		    size = symtab_hdr->sh_info;
-		    size *= (sizeof (bfd_signed_vma) + sizeof(char));
+		    size *= (sizeof (bfd_signed_vma)
+			     + sizeof (bfd_vma) + sizeof(char));
 		    local_got_refcounts = bfd_zalloc (abfd, size);
 		    if (local_got_refcounts == NULL)
 		      return FALSE;
 		    elf_local_got_refcounts (abfd) = local_got_refcounts;
+		    elf_i386_local_tlsdesc_gotent (abfd)
+		      = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info);
 		    elf_i386_local_got_tls_type (abfd)
-		      = (char *) (local_got_refcounts + symtab_hdr->sh_info);
+		      = (char *) (local_got_refcounts + 2 * symtab_hdr->sh_info);
 		  }
 		local_got_refcounts[r_symndx] += 1;
 		old_tls_type = elf_i386_local_got_tls_type (abfd) [r_symndx];
@@ -1007,11 +1066,14 @@ elf_i386_check_relocs (bfd *abfd,
 	    /* If a TLS symbol is accessed using IE at least once,
 	       there is no point to use dynamic model for it.  */
 	    else if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN
-		     && (old_tls_type != GOT_TLS_GD
+		     && (! GOT_TLS_GD_ANY_P (old_tls_type)
 			 || (tls_type & GOT_TLS_IE) == 0))
 	      {
-		if ((old_tls_type & GOT_TLS_IE) && tls_type == GOT_TLS_GD)
+		if ((old_tls_type & GOT_TLS_IE) && GOT_TLS_GD_ANY_P (tls_type))
 		  tls_type = old_tls_type;
+		else if (GOT_TLS_GD_ANY_P (old_tls_type)
+			 && GOT_TLS_GD_ANY_P (tls_type))
+		  tls_type |= old_tls_type;
 		else
 		  {
 		    (*_bfd_error_handler)
@@ -1319,6 +1381,8 @@ elf_i386_gc_sweep_hook (bfd *abfd,
 	  break;
 
 	case R_386_TLS_GD:
+	case R_386_TLS_GOTDESC:
+	case R_386_TLS_DESC_CALL:
 	case R_386_TLS_IE_32:
 	case R_386_TLS_IE:
 	case R_386_TLS_GOTIE:
@@ -1582,6 +1646,7 @@ allocate_dynrelocs (struct elf_link_hash
 
 	  /* We also need to make an entry in the .rel.plt section.  */
 	  htab->srelplt->size += sizeof (Elf32_External_Rel);
+	  htab->srelplt->reloc_count++;
 
 	  if (htab->is_vxworks && !info->shared)
 	    {
@@ -1615,6 +1680,9 @@ allocate_dynrelocs (struct elf_link_hash
       h->needs_plt = 0;
     }
 
+  eh = (struct elf_i386_link_hash_entry *) h;
+  eh->tlsdesc_got = (bfd_vma) -1;
+
   /* If R_386_TLS_{IE_32,IE,GOTIE} symbol is now local to the binary,
      make it a R_386_TLS_LE_32 requiring no TLS entry.  */
   if (h->got.refcount > 0
@@ -1638,11 +1706,22 @@ allocate_dynrelocs (struct elf_link_hash
 	}
 
       s = htab->sgot;
-      h->got.offset = s->size;
-      s->size += 4;
-      /* R_386_TLS_GD needs 2 consecutive GOT slots.  */
-      if (tls_type == GOT_TLS_GD || tls_type == GOT_TLS_IE_BOTH)
-	s->size += 4;
+      if (GOT_TLS_GDESC_P (tls_type))
+	{
+	  eh->tlsdesc_got = htab->sgotplt->size
+	    - elf_i386_compute_jump_table_size (htab);
+	  htab->sgotplt->size += 8;
+	  h->got.offset = (bfd_vma) -2;
+	}
+      if (! GOT_TLS_GDESC_P (tls_type)
+	  || GOT_TLS_GD_P (tls_type))
+	{
+	  h->got.offset = s->size;
+	  s->size += 4;
+	  /* R_386_TLS_GD needs 2 consecutive GOT slots.  */
+	  if (GOT_TLS_GD_P (tls_type) || tls_type == GOT_TLS_IE_BOTH)
+	    s->size += 4;
+	}
       dyn = htab->elf.dynamic_sections_created;
       /* R_386_TLS_IE_32 needs one dynamic relocation,
 	 R_386_TLS_IE resp. R_386_TLS_GOTIE needs one dynamic relocation,
@@ -1651,21 +1730,23 @@ allocate_dynrelocs (struct elf_link_hash
 	 global.  */
       if (tls_type == GOT_TLS_IE_BOTH)
 	htab->srelgot->size += 2 * sizeof (Elf32_External_Rel);
-      else if ((tls_type == GOT_TLS_GD && h->dynindx == -1)
+      else if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1)
 	       || (tls_type & GOT_TLS_IE))
 	htab->srelgot->size += sizeof (Elf32_External_Rel);
-      else if (tls_type == GOT_TLS_GD)
+      else if (GOT_TLS_GD_P (tls_type))
 	htab->srelgot->size += 2 * sizeof (Elf32_External_Rel);
-      else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-		|| h->root.type != bfd_link_hash_undefweak)
+      else if (! GOT_TLS_GDESC_P (tls_type)
+	       && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+		   || h->root.type != bfd_link_hash_undefweak)
 	       && (info->shared
 		   || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
 	htab->srelgot->size += sizeof (Elf32_External_Rel);
+      if (GOT_TLS_GDESC_P (tls_type))
+	htab->srelplt->size += sizeof (Elf32_External_Rel);
     }
   else
     h->got.offset = (bfd_vma) -1;
 
-  eh = (struct elf_i386_link_hash_entry *) h;
   if (eh->dyn_relocs == NULL)
     return TRUE;
 
@@ -1813,6 +1894,7 @@ elf_i386_size_dynamic_sections (bfd *out
       bfd_signed_vma *local_got;
       bfd_signed_vma *end_local_got;
       char *local_tls_type;
+      bfd_vma *local_tlsdesc_gotent;
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
       asection *srel;
@@ -1855,25 +1937,42 @@ elf_i386_size_dynamic_sections (bfd *out
       locsymcount = symtab_hdr->sh_info;
       end_local_got = local_got + locsymcount;
       local_tls_type = elf_i386_local_got_tls_type (ibfd);
+      local_tlsdesc_gotent = elf_i386_local_tlsdesc_gotent (ibfd);
       s = htab->sgot;
       srel = htab->srelgot;
-      for (; local_got < end_local_got; ++local_got, ++local_tls_type)
+      for (; local_got < end_local_got;
+	   ++local_got, ++local_tls_type, ++local_tlsdesc_gotent)
 	{
+	  *local_tlsdesc_gotent = (bfd_vma) -1;
 	  if (*local_got > 0)
 	    {
-	      *local_got = s->size;
-	      s->size += 4;
-	      if (*local_tls_type == GOT_TLS_GD
-		  || *local_tls_type == GOT_TLS_IE_BOTH)
-		s->size += 4;
+	      if (GOT_TLS_GDESC_P (*local_tls_type))
+		{
+		  *local_tlsdesc_gotent = htab->sgotplt->size
+		    - elf_i386_compute_jump_table_size (htab);
+		  htab->sgotplt->size += 8;
+		  *local_got = (bfd_vma) -2;
+		}
+	      if (! GOT_TLS_GDESC_P (*local_tls_type)
+		  || GOT_TLS_GD_P (*local_tls_type))
+		{
+		  *local_got = s->size;
+		  s->size += 4;
+		  if (GOT_TLS_GD_P (*local_tls_type)
+		      || *local_tls_type == GOT_TLS_IE_BOTH)
+		    s->size += 4;
+		}
 	      if (info->shared
-		  || *local_tls_type == GOT_TLS_GD
+		  || GOT_TLS_GD_ANY_P (*local_tls_type)
 		  || (*local_tls_type & GOT_TLS_IE))
 		{
 		  if (*local_tls_type == GOT_TLS_IE_BOTH)
 		    srel->size += 2 * sizeof (Elf32_External_Rel);
-		  else
+		  else if (GOT_TLS_GD_P (*local_tls_type)
+			   || ! GOT_TLS_GDESC_P (*local_tls_type))
 		    srel->size += sizeof (Elf32_External_Rel);
+		  if (GOT_TLS_GDESC_P (*local_tls_type))
+		    htab->srelplt->size += sizeof (Elf32_External_Rel);
 		}
 	    }
 	  else
@@ -1917,6 +2016,14 @@ elf_i386_size_dynamic_sections (bfd *out
      sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
 
+  /* For every jump slot reserved in the sgotplt, reloc_count is
+     incremented.  However, when we reserve space for TLS descriptors,
+     it's not incremented, so in order to compute the space reserved
+     for them, it suffices to multiply the reloc count by the jump
+     slot size.  */
+  if (htab->srelplt)
+    htab->sgotplt_jump_table_size = htab->srelplt->reloc_count * 4;
+
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
   relocs = FALSE;
@@ -1948,7 +2055,8 @@ elf_i386_size_dynamic_sections (bfd *out
 
 	  /* We use the reloc_count field as a counter if we need
 	     to copy relocs into the output file.  */
-	  s->reloc_count = 0;
+	  if (s != htab->srelplt)
+	    s->reloc_count = 0;
 	}
       else
 	{
@@ -2035,6 +2143,41 @@ elf_i386_size_dynamic_sections (bfd *out
   return TRUE;
 }
 
+static bfd_boolean
+elf_i386_always_size_sections (bfd *output_bfd,
+			       struct bfd_link_info *info)
+{
+  asection *tls_sec = elf_hash_table (info)->tls_sec;
+
+  if (tls_sec)
+    {
+      struct elf_link_hash_entry *tlsbase;
+
+      tlsbase = elf_link_hash_lookup (elf_hash_table (info),
+				      "_TLS_MODULE_BASE_",
+				      FALSE, FALSE, FALSE);
+
+      if (tlsbase && tlsbase->type == STT_TLS)
+	{
+	  struct bfd_link_hash_entry *bh = NULL;
+	  const struct elf_backend_data *bed
+	    = get_elf_backend_data (output_bfd);
+
+	  if (!(_bfd_generic_link_add_one_symbol
+		(info, output_bfd, "_TLS_MODULE_BASE_", BSF_LOCAL,
+		 tls_sec, 0, NULL, FALSE,
+		 bed->collect, &bh)))
+	    return FALSE;
+	  tlsbase = (struct elf_link_hash_entry *)bh;
+	  tlsbase->def_regular = 1;
+	  tlsbase->other = STV_HIDDEN;
+	  (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE);
+	}
+    }
+
+  return TRUE;
+}
+
 /* Set the correct type for an x86 ELF section.  We do this by the
    section name, which is a hack, but ought to work.  */
 
@@ -2112,6 +2255,7 @@ elf_i386_relocate_section (bfd *output_b
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
   bfd_vma *local_got_offsets;
+  bfd_vma *local_tlsdesc_gotents;
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
 
@@ -2119,6 +2263,7 @@ elf_i386_relocate_section (bfd *output_b
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (input_bfd);
   local_got_offsets = elf_local_got_offsets (input_bfd);
+  local_tlsdesc_gotents = elf_i386_local_tlsdesc_gotent (input_bfd);
 
   rel = relocs;
   relend = relocs + input_section->reloc_count;
@@ -2130,7 +2275,7 @@ elf_i386_relocate_section (bfd *output_b
       struct elf_link_hash_entry *h;
       Elf_Internal_Sym *sym;
       asection *sec;
-      bfd_vma off;
+      bfd_vma off, offplt;
       bfd_vma relocation;
       bfd_boolean unresolved_reloc;
       bfd_reloc_status_type r;
@@ -2552,6 +2697,8 @@ elf_i386_relocate_section (bfd *output_b
 	  /* Fall through */
 
 	case R_386_TLS_GD:
+	case R_386_TLS_GOTDESC:
+	case R_386_TLS_DESC_CALL:
 	case R_386_TLS_IE_32:
 	case R_386_TLS_GOTIE:
 	  r_type = elf_i386_tls_transition (info, r_type, h == NULL);
@@ -2566,7 +2713,9 @@ elf_i386_relocate_section (bfd *output_b
 	    }
 	  if (tls_type == GOT_TLS_IE)
 	    tls_type = GOT_TLS_IE_NEG;
-	  if (r_type == R_386_TLS_GD)
+	  if (r_type == R_386_TLS_GD
+	      || r_type == R_386_TLS_GOTDESC
+	      || r_type == R_386_TLS_DESC_CALL)
 	    {
 	      if (tls_type == GOT_TLS_IE_POS)
 		r_type = R_386_TLS_GOTIE;
@@ -2640,6 +2789,67 @@ elf_i386_relocate_section (bfd *output_b
 		  rel++;
 		  continue;
 		}
+	      else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC)
+		{
+		  /* GDesc -> LE transition.
+		     It's originally something like:
+		     leal x@tlsdesc(%ebx), %eax
+
+		     aoliva FIXME.  Decide whether to change it to:
+		     gs: .byte 0x65 ; movl $x@ntpoff, %eax
+		     or
+		     leal x@ntpoff, %eax
+		     
+		     Registers other than %eax may be set up here.  */
+		  
+		  unsigned int val, type;
+		  bfd_vma roff;
+
+		  /* First, make sure it's a leal adding ebx to a
+		     32-bit offset into any register, although it's
+		     probably almost always going to be eax.  */
+		  roff = rel->r_offset;
+		  BFD_ASSERT (roff >= 2);
+		  type = bfd_get_8 (input_bfd, contents + roff - 2);
+		  BFD_ASSERT (type == 0x8d);
+		  val = bfd_get_8 (input_bfd, contents + roff - 1);
+		  BFD_ASSERT ((val & 0xc7) == 0x83);
+		  BFD_ASSERT (roff + 4 <= input_section->size);
+
+		  /* Now modify the instruction as appropriate.  */
+		  bfd_put_8 (output_bfd, 0x65, contents + roff - 2);
+		  /* aoliva FIXME: remove the above and xor the byte
+		     below with 0x86.  */
+		  bfd_put_8 (output_bfd, 0xb8 | ((val >> 3) & 7),
+			     contents + roff - 1);
+		  bfd_put_32 (output_bfd, -tpoff (info, relocation),
+			      contents + roff);
+		  continue;
+		}
+	      else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL)
+		{
+		  /* GDesc -> LE transition.
+		     It's originally:
+		     call *(%eax)
+		     Turn it into:
+		     movl %eax, %eax  */
+		  
+		  unsigned int val, type;
+		  bfd_vma roff;
+
+		  /* First, make sure it's a call *(%eax).  */
+		  roff = rel->r_offset;
+		  BFD_ASSERT (roff + 2 <= input_section->size);
+		  type = bfd_get_8 (input_bfd, contents + roff);
+		  BFD_ASSERT (type == 0xff);
+		  val = bfd_get_8 (input_bfd, contents + roff + 1);
+		  BFD_ASSERT (val == 0x10);
+
+		  /* Now modify the instruction as appropriate.  */
+		  bfd_put_8 (output_bfd, 0x89, contents + roff);
+		  bfd_put_8 (output_bfd, 0xc0, contents + roff + 1);
+		  continue;
+		}
 	      else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_IE)
 		{
 		  unsigned int val, type;
@@ -2754,13 +2964,17 @@ elf_i386_relocate_section (bfd *output_b
 	    abort ();
 
 	  if (h != NULL)
-	    off = h->got.offset;
+	    {
+	      off = h->got.offset;
+	      offplt = elf_i386_hash_entry (h)->tlsdesc_got;
+	    }
 	  else
 	    {
 	      if (local_got_offsets == NULL)
 		abort ();
 
 	      off = local_got_offsets[r_symndx];
+	      offplt = local_tlsdesc_gotents[r_symndx];
 	    }
 
 	  if ((off & 1) != 0)
@@ -2770,35 +2984,77 @@ elf_i386_relocate_section (bfd *output_b
 	      Elf_Internal_Rela outrel;
 	      bfd_byte *loc;
 	      int dr_type, indx;
+	      asection *sreloc;
 
 	      if (htab->srelgot == NULL)
 		abort ();
 
+	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
+
+	      if (GOT_TLS_GDESC_P (tls_type))
+		{
+		  outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_DESC);
+		  BFD_ASSERT (htab->sgotplt_jump_table_size + offplt + 8
+			      <= htab->sgotplt->size);
+		  outrel.r_offset = (htab->sgotplt->output_section->vma
+				     + htab->sgotplt->output_offset
+				     + offplt
+				     + htab->sgotplt_jump_table_size);
+		  sreloc = htab->srelplt;
+		  loc = sreloc->contents;
+		  loc += sreloc->reloc_count++
+		    * sizeof (Elf32_External_Rel);
+		  BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
+			      <= sreloc->contents + sreloc->size);
+		  bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
+		  if (indx == 0)
+		    {
+		      BFD_ASSERT (! unresolved_reloc);
+		      bfd_put_32 (output_bfd,
+				  relocation - dtpoff_base (info),
+				  htab->sgotplt->contents + offplt
+				  + htab->sgotplt_jump_table_size + 4);
+		    }
+		  else
+		    {
+		      bfd_put_32 (output_bfd, 0,
+				  htab->sgotplt->contents + offplt
+				  + htab->sgotplt_jump_table_size + 4);
+		    }
+		}
+
+	      sreloc = htab->srelgot;
+
 	      outrel.r_offset = (htab->sgot->output_section->vma
 				 + htab->sgot->output_offset + off);
 
-	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
-	      if (r_type == R_386_TLS_GD)
+	      if (GOT_TLS_GD_P (tls_type))
 		dr_type = R_386_TLS_DTPMOD32;
+	      else if (GOT_TLS_GDESC_P (tls_type))
+		goto dr_done;
 	      else if (tls_type == GOT_TLS_IE_POS)
 		dr_type = R_386_TLS_TPOFF;
 	      else
 		dr_type = R_386_TLS_TPOFF32;
+
 	      if (dr_type == R_386_TLS_TPOFF && indx == 0)
 		bfd_put_32 (output_bfd, relocation - dtpoff_base (info),
 			    htab->sgot->contents + off);
 	      else if (dr_type == R_386_TLS_TPOFF32 && indx == 0)
 		bfd_put_32 (output_bfd, dtpoff_base (info) - relocation,
 			    htab->sgot->contents + off);
-	      else
+	      else if (dr_type != R_386_TLS_DESC)
 		bfd_put_32 (output_bfd, 0,
 			    htab->sgot->contents + off);
 	      outrel.r_info = ELF32_R_INFO (indx, dr_type);
-	      loc = htab->srelgot->contents;
-	      loc += htab->srelgot->reloc_count++ * sizeof (Elf32_External_Rel);
+
+	      loc = sreloc->contents;
+	      loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel);
+	      BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
+			  <= sreloc->contents + sreloc->size);
 	      bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
 
-	      if (r_type == R_386_TLS_GD)
+	      if (GOT_TLS_GD_P (tls_type))
 		{
 		  if (indx == 0)
 		    {
@@ -2814,8 +3070,10 @@ elf_i386_relocate_section (bfd *output_b
 		      outrel.r_info = ELF32_R_INFO (indx,
 						    R_386_TLS_DTPOFF32);
 		      outrel.r_offset += 4;
-		      htab->srelgot->reloc_count++;
+		      sreloc->reloc_count++;
 		      loc += sizeof (Elf32_External_Rel);
+		      BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
+				  <= sreloc->contents + sreloc->size);
 		      bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
 		    }
 		}
@@ -2826,25 +3084,33 @@ elf_i386_relocate_section (bfd *output_b
 			      htab->sgot->contents + off + 4);
 		  outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_TPOFF);
 		  outrel.r_offset += 4;
-		  htab->srelgot->reloc_count++;
+		  sreloc->reloc_count++;
 		  loc += sizeof (Elf32_External_Rel);
 		  bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
 		}
 
+	    dr_done:
 	      if (h != NULL)
 		h->got.offset |= 1;
 	      else
 		local_got_offsets[r_symndx] |= 1;
 	    }
 
-	  if (off >= (bfd_vma) -2)
+	  if (off >= (bfd_vma) -2
+	      && ! GOT_TLS_GDESC_P (tls_type))
 	    abort ();
-	  if (r_type == ELF32_R_TYPE (rel->r_info))
+	  if (r_type == R_386_TLS_GOTDESC
+	      || r_type == R_386_TLS_DESC_CALL)
+	    {
+	      relocation = htab->sgotplt_jump_table_size + offplt;
+	      unresolved_reloc = FALSE;
+	    }
+	  else if (r_type == ELF32_R_TYPE (rel->r_info))
 	    {
 	      bfd_vma g_o_t = htab->sgotplt->output_section->vma
 			      + htab->sgotplt->output_offset;
 	      relocation = htab->sgot->output_section->vma
-			   + htab->sgot->output_offset + off - g_o_t;
+		+ htab->sgot->output_offset + off - g_o_t;
 	      if ((r_type == R_386_TLS_IE || r_type == R_386_TLS_GOTIE)
 		  && tls_type == GOT_TLS_IE_BOTH)
 		relocation += 4;
@@ -2852,7 +3118,7 @@ elf_i386_relocate_section (bfd *output_b
 		relocation += g_o_t;
 	      unresolved_reloc = FALSE;
 	    }
-	  else
+	  else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD)
 	    {
 	      unsigned int val, type;
 	      bfd_vma roff;
@@ -2916,6 +3182,97 @@ elf_i386_relocate_section (bfd *output_b
 	      rel++;
 	      continue;
 	    }
+	  else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC)
+	    {
+	      /* GDesc -> IE transition.
+		 It's originally something like:
+		 leal x@tlsdesc(%ebx), %eax
+
+		 aoliva FIXME: decide whether to change it to:
+		 movl x@gotntpoff(%ebx), %eax # before movl %eax,%eax
+		 or
+		 leal x@gotntpoff(%ebx), %eax # before movl (%eax),%eax
+		 but the latter won't work if we need to negate the
+		 loaded value.
+		     
+		 Registers other than %eax may be set up here.  */
+		  
+	      unsigned int val, type;
+	      bfd_vma roff;
+
+	      /* First, make sure it's a leal adding ebx to a 32-bit
+		 offset into any register, although it's probably
+		 almost always going to be eax.  */
+	      roff = rel->r_offset;
+	      BFD_ASSERT (roff >= 2);
+	      type = bfd_get_8 (input_bfd, contents + roff - 2);
+	      BFD_ASSERT (type == 0x8d);
+	      val = bfd_get_8 (input_bfd, contents + roff - 1);
+	      BFD_ASSERT ((val & 0xc7) == 0x83);
+	      BFD_ASSERT (roff + 4 <= input_section->size);
+
+	      /* Now modify the instruction as appropriate.  */
+	      /* To turn a leal into a movl in the form we use it, it
+		 suffices to change the first byte from 0x8d to 0x8b.
+		 aoliva FIXME: should we decide to keep the leal, all
+		 we have to do is remove the statement below, and
+		 adjust the relaxation of R_386_TLS_DESC_CALL.  */
+	      bfd_put_8 (output_bfd, 0x8b, contents + roff - 2);
+
+	      if (tls_type == GOT_TLS_IE_BOTH)
+		off += 4;
+
+	      bfd_put_32 (output_bfd,
+			  htab->sgot->output_section->vma
+			  + htab->sgot->output_offset + off
+			  - htab->sgotplt->output_section->vma
+			  - htab->sgotplt->output_offset,
+			  contents + roff);
+	      continue;
+	    }
+	  else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL)
+	    {
+	      /* GDesc -> IE transition.
+		 It's originally:
+		 calll *(%eax)
+
+		 aoliva FIXME: decide whether to change it to:
+		 movl %eax,%eax # after movl x@gotntpoff(%ebx), %eax
+		 or
+		 movl (%eax),%eax # after leal x@gotntpoff(%ebx), %eax
+
+	         Either one works unless we have to negate the
+	         offset.  */
+		  
+	      unsigned int val, type;
+	      bfd_vma roff;
+
+	      /* First, make sure it's a call *(%eax).  */
+	      roff = rel->r_offset;
+	      BFD_ASSERT (roff + 2 <= input_section->size);
+	      type = bfd_get_8 (input_bfd, contents + roff);
+	      BFD_ASSERT (type == 0xff);
+	      val = bfd_get_8 (input_bfd, contents + roff + 1);
+	      BFD_ASSERT (val == 0x10);
+
+	      /* Now modify the instruction as appropriate.  */
+	      if (tls_type != GOT_TLS_IE_NEG)
+		{
+		  /* movl %eax,%eax */
+		  bfd_put_8 (output_bfd, 0x89, contents + roff);
+		  bfd_put_8 (output_bfd, 0xc0, contents + roff + 1);
+		}
+	      else
+		{
+		  /* negl %eax */
+		  bfd_put_8 (output_bfd, 0xf7, contents + roff);
+		  bfd_put_8 (output_bfd, 0xd8, contents + roff + 1);
+		}
+
+	      continue;
+	    }
+	  else
+	    BFD_ASSERT (FALSE);
 	  break;
 
 	case R_386_TLS_LDM:
@@ -3223,7 +3580,7 @@ elf_i386_finish_dynamic_symbol (bfd *out
     }
 
   if (h->got.offset != (bfd_vma) -1
-      && elf_i386_hash_entry(h)->tls_type != GOT_TLS_GD
+      && ! GOT_TLS_GD_ANY_P (elf_i386_hash_entry(h)->tls_type)
       && (elf_i386_hash_entry(h)->tls_type & GOT_TLS_IE) == 0)
     {
       Elf_Internal_Rela rel;
@@ -3558,6 +3915,7 @@ elf_i386_plt_sym_val (bfd_vma i, const a
 #define elf_backend_reloc_type_class	      elf_i386_reloc_type_class
 #define elf_backend_relocate_section	      elf_i386_relocate_section
 #define elf_backend_size_dynamic_sections     elf_i386_size_dynamic_sections
+#define elf_backend_always_size_sections      elf_i386_always_size_sections
 #define elf_backend_plt_sym_val		      elf_i386_plt_sym_val
 
 #include "elf32-target.h"
Index: bfd/elf64-x86-64.c
===================================================================
RCS file: /cvs/uberbaum/./bfd/elf64-x86-64.c,v
retrieving revision 1.107
diff -u -p -r1.107 elf64-x86-64.c
--- bfd/elf64-x86-64.c 31 Aug 2005 23:45:46 -0000 1.107
+++ bfd/elf64-x86-64.c 15 Sep 2005 22:38:19 -0000
@@ -112,12 +112,24 @@ static reloc_howto_type x86_64_elf_howto
   HOWTO(R_X86_64_GOTPC32, 0, 2, 32, TRUE, 0, complain_overflow_signed,
 	bfd_elf_generic_reloc, "R_X86_64_GOTPC32",
 	FALSE, 0xffffffff, 0xffffffff, TRUE),
+  HOWTO(R_X86_64_GOTPC32_TLSDESC, 0, 2, 32, TRUE, 0,
+	complain_overflow_bitfield, bfd_elf_generic_reloc,
+	"R_X86_64_GOTPC32_TLSDESC",
+	FALSE, 0xffffffff, 0xffffffff, TRUE),
+  HOWTO(R_X86_64_TLSDESC, 0, 4, 64, FALSE, 0,
+	complain_overflow_bitfield, bfd_elf_generic_reloc,
+	"R_X86_64_TLSDESC",
+	FALSE, MINUS_ONE, MINUS_ONE, FALSE),
+  HOWTO(R_X86_64_TLSDESC_CALL, 0, 0, 0, FALSE, 0,
+	complain_overflow_dont, bfd_elf_generic_reloc,
+	"R_X86_64_TLSDESC_CALL", 
+	FALSE, 0, 0, FALSE),
 
   /* We have a gap in the reloc numbers here.
      R_X86_64_standard counts the number up to this point, and
      R_X86_64_vt_offset is the value to subtract from a reloc type of
      R_X86_64_GNU_VT* to form an index into this table.  */
-#define R_X86_64_standard (R_X86_64_GOTPC32 + 1)
+#define R_X86_64_standard (R_X86_64_TLSDESC_CALL + 1)
 #define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard)
 
 /* GNU extension to record C++ vtable hierarchy.  */
@@ -166,6 +178,9 @@ static const struct elf_reloc_map x86_64
   { BFD_RELOC_64_PCREL,		R_X86_64_PC64, },
   { BFD_RELOC_X86_64_GOTOFF64,	R_X86_64_GOTOFF64, },
   { BFD_RELOC_X86_64_GOTPC32,	R_X86_64_GOTPC32, },
+  { BFD_RELOC_X86_64_GOTPC32_TLSDESC, R_X86_64_GOTPC32_TLSDESC, },
+  { BFD_RELOC_X86_64_TLSDESC,	R_X86_64_TLSDESC, },
+  { BFD_RELOC_X86_64_TLSDESC_CALL, R_X86_64_TLSDESC_CALL, },
   { BFD_RELOC_VTABLE_INHERIT,	R_X86_64_GNU_VTINHERIT, },
   { BFD_RELOC_VTABLE_ENTRY,	R_X86_64_GNU_VTENTRY, },
 };
@@ -353,7 +368,20 @@ struct elf64_x86_64_link_hash_entry
 #define GOT_NORMAL	1
 #define GOT_TLS_GD	2
 #define GOT_TLS_IE	3
+#define GOT_TLS_GDESC	4
+#define GOT_TLS_GD_BOTH_P(type) \
+  ((type) == (GOT_TLS_GD | GOT_TLS_GDESC))
+#define GOT_TLS_GD_P(type) \
+  ((type) == GOT_TLS_GD || GOT_TLS_GD_BOTH_P (type))
+#define GOT_TLS_GDESC_P(type) \
+  ((type) == GOT_TLS_GDESC || GOT_TLS_GD_BOTH_P (type))
+#define GOT_TLS_GD_ANY_P(type) \
+  (GOT_TLS_GD_P (type) || GOT_TLS_GDESC_P (type))
   unsigned char tls_type;
+
+  /* Offset of the GOTPLT entry reserved for the TLS descriptor,
+     starting at the end of the jump table.  */
+  bfd_vma tlsdesc_got;
 };
 
 #define elf64_x86_64_hash_entry(ent) \
@@ -365,6 +393,9 @@ struct elf64_x86_64_obj_tdata
 
   /* tls_type for each local got entry.  */
   char *local_got_tls_type;
+
+  /* GOTPLT entries for TLS descriptors.  */
+  bfd_vma *local_tlsdesc_gotent;
 };
 
 #define elf64_x86_64_tdata(abfd) \
@@ -373,6 +404,8 @@ struct elf64_x86_64_obj_tdata
 #define elf64_x86_64_local_got_tls_type(abfd) \
   (elf64_x86_64_tdata (abfd)->local_got_tls_type)
 
+#define elf64_x86_64_local_tlsdesc_gotent(abfd) \
+  (elf64_x86_64_tdata (abfd)->local_tlsdesc_gotent)
 
 /* x86-64 ELF linker hash table.  */
 
@@ -389,11 +422,23 @@ struct elf64_x86_64_link_hash_table
   asection *sdynbss;
   asection *srelbss;
 
+  /* The offset into splt of the PLT entry for the TLS descriptor
+     resolver.  Special values are 0, if not necessary (or not found
+     to be necessary yet), and -1 if needed but not determined
+     yet.  */
+  bfd_vma tlsdesc_plt;
+  /* The offset into sgot of the GOT entry used by the PLT entry
+     above.  */
+  bfd_vma tlsdesc_got;
+
   union {
     bfd_signed_vma refcount;
     bfd_vma offset;
   } tls_ld_got;
 
+  /* The amount of space used by the jump slots in the GOT.  */
+  bfd_vma sgotplt_jump_table_size;
+
   /* Small local sym to section mapping cache.  */
   struct sym_sec_cache sym_sec;
 };
@@ -403,6 +448,9 @@ struct elf64_x86_64_link_hash_table
 #define elf64_x86_64_hash_table(p) \
   ((struct elf64_x86_64_link_hash_table *) ((p)->hash))
 
+#define elf64_x86_64_compute_jump_table_size(htab) \
+  ((htab)->srelplt->reloc_count * GOT_ENTRY_SIZE)
+
 /* Create an entry in an x86-64 ELF linker hash table.	*/
 
 static struct bfd_hash_entry *
@@ -428,6 +476,7 @@ link_hash_newfunc (struct bfd_hash_entry
       eh = (struct elf64_x86_64_link_hash_entry *) entry;
       eh->dyn_relocs = NULL;
       eh->tls_type = GOT_UNKNOWN;
+      eh->tlsdesc_got = (bfd_vma) -1;
     }
 
   return entry;
@@ -459,7 +508,10 @@ elf64_x86_64_link_hash_table_create (bfd
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
   ret->sym_sec.abfd = NULL;
+  ret->tlsdesc_plt = 0;
+  ret->tlsdesc_got = 0;
   ret->tls_ld_got.refcount = 0;
+  ret->sgotplt_jump_table_size = 0;
 
   return &ret->elf.root;
 }
@@ -619,6 +671,8 @@ elf64_x86_64_tls_transition (struct bfd_
   switch (r_type)
     {
     case R_X86_64_TLSGD:
+    case R_X86_64_GOTPC32_TLSDESC:
+    case R_X86_64_TLSDESC_CALL:
     case R_X86_64_GOTTPOFF:
       if (is_local)
 	return R_X86_64_TPOFF32;
@@ -709,6 +763,8 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 	case R_X86_64_GOT32:
 	case R_X86_64_GOTPCREL:
 	case R_X86_64_TLSGD:
+	case R_X86_64_GOTPC32_TLSDESC:
+	case R_X86_64_TLSDESC_CALL:
 	  /* This symbol requires a global offset table entry.	*/
 	  {
 	    int tls_type, old_tls_type;
@@ -718,6 +774,9 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 	      default: tls_type = GOT_NORMAL; break;
 	      case R_X86_64_TLSGD: tls_type = GOT_TLS_GD; break;
 	      case R_X86_64_GOTTPOFF: tls_type = GOT_TLS_IE; break;
+	      case R_X86_64_GOTPC32_TLSDESC:
+	      case R_X86_64_TLSDESC_CALL:
+		tls_type = GOT_TLS_GDESC; break;
 	      }
 
 	    if (h != NULL)
@@ -736,14 +795,17 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 		    bfd_size_type size;
 
 		    size = symtab_hdr->sh_info;
-		    size *= sizeof (bfd_signed_vma) + sizeof (char);
+		    size *= sizeof (bfd_signed_vma)
+		      + sizeof (bfd_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;
+		    elf64_x86_64_local_tlsdesc_gotent (abfd)
+		      = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info);
 		    elf64_x86_64_local_got_tls_type (abfd)
-		      = (char *) (local_got_refcounts + symtab_hdr->sh_info);
+		      = (char *) (local_got_refcounts + 2 * symtab_hdr->sh_info);
 		  }
 		local_got_refcounts[r_symndx] += 1;
 		old_tls_type
@@ -753,10 +815,14 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 	    /* 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))
+		&& (! GOT_TLS_GD_ANY_P (old_tls_type)
+		    || tls_type != GOT_TLS_IE))
 	      {
-		if (old_tls_type == GOT_TLS_IE && tls_type == GOT_TLS_GD)
+		if (old_tls_type == GOT_TLS_IE && GOT_TLS_GD_ANY_P (tls_type))
 		  tls_type = old_tls_type;
+		else if (GOT_TLS_GD_ANY_P (old_tls_type)
+			 && GOT_TLS_GD_ANY_P (tls_type))
+		  tls_type |= old_tls_type;
 		else
 		  {
 		    (*_bfd_error_handler)
@@ -1104,6 +1170,8 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, s
 	  break;
 
 	case R_X86_64_TLSGD:
+	case R_X86_64_GOTPC32_TLSDESC:
+	case R_X86_64_TLSDESC_CALL:
 	case R_X86_64_GOTTPOFF:
 	case R_X86_64_GOT32:
 	case R_X86_64_GOTPCREL:
@@ -1371,6 +1439,7 @@ allocate_dynrelocs (struct elf_link_hash
 
 	  /* We also need to make an entry in the .rela.plt section.  */
 	  htab->srelplt->size += sizeof (Elf64_External_Rela);
+	  htab->srelplt->reloc_count++;
 	}
       else
 	{
@@ -1384,6 +1453,9 @@ allocate_dynrelocs (struct elf_link_hash
       h->needs_plt = 0;
     }
 
+  eh = (struct elf64_x86_64_link_hash_entry *) h;
+  eh->tlsdesc_got = (bfd_vma) -1;
+  
   /* If R_X86_64_GOTTPOFF symbol is now local to the binary,
      make it a R_X86_64_TPOFF32 requiring no GOT entry.  */
   if (h->got.refcount > 0
@@ -1406,31 +1478,46 @@ allocate_dynrelocs (struct elf_link_hash
 	    return FALSE;
 	}
 
-      s = htab->sgot;
-      h->got.offset = s->size;
-      s->size += GOT_ENTRY_SIZE;
-      /* R_X86_64_TLSGD needs 2 consecutive GOT slots.  */
-      if (tls_type == GOT_TLS_GD)
-	s->size += GOT_ENTRY_SIZE;
+      if (GOT_TLS_GDESC_P (tls_type))
+	{
+	  eh->tlsdesc_got = htab->sgotplt->size
+	    - elf64_x86_64_compute_jump_table_size (htab);
+	  htab->sgotplt->size += 2 * GOT_ENTRY_SIZE;
+	  h->got.offset = (bfd_vma) -2;
+	}
+      if (! GOT_TLS_GDESC_P (tls_type)
+	  || GOT_TLS_GD_P (tls_type))
+	{
+	  s = htab->sgot;
+	  h->got.offset = s->size;
+	  s->size += GOT_ENTRY_SIZE;
+	  if (GOT_TLS_GD_P (tls_type))
+	    s->size += GOT_ENTRY_SIZE;
+	}
       dyn = htab->elf.dynamic_sections_created;
       /* R_X86_64_TLSGD needs one dynamic relocation if local symbol
 	 and two if global.
 	 R_X86_64_GOTTPOFF needs one dynamic relocation.  */
-      if ((tls_type == GOT_TLS_GD && h->dynindx == -1)
+      if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1)
 	  || tls_type == GOT_TLS_IE)
 	htab->srelgot->size += sizeof (Elf64_External_Rela);
-      else if (tls_type == GOT_TLS_GD)
+      else if (GOT_TLS_GD_P (tls_type))
 	htab->srelgot->size += 2 * sizeof (Elf64_External_Rela);
-      else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-		|| h->root.type != bfd_link_hash_undefweak)
+      else if (! GOT_TLS_GDESC_P (tls_type)
+	       && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+		   || h->root.type != bfd_link_hash_undefweak)
 	       && (info->shared
 		   || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
 	htab->srelgot->size += sizeof (Elf64_External_Rela);
+      if (GOT_TLS_GDESC_P (tls_type))
+	{
+	  htab->srelplt->size += sizeof (Elf64_External_Rela);
+	  htab->tlsdesc_plt = (bfd_vma) -1;
+	}
     }
   else
     h->got.offset = (bfd_vma) -1;
 
-  eh = (struct elf64_x86_64_link_hash_entry *) h;
   if (eh->dyn_relocs == NULL)
     return TRUE;
 
@@ -1578,6 +1665,7 @@ elf64_x86_64_size_dynamic_sections (bfd 
       bfd_signed_vma *local_got;
       bfd_signed_vma *end_local_got;
       char *local_tls_type;
+      bfd_vma *local_tlsdesc_gotent;
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
       asection *srel;
@@ -1621,20 +1709,43 @@ elf64_x86_64_size_dynamic_sections (bfd 
       locsymcount = symtab_hdr->sh_info;
       end_local_got = local_got + locsymcount;
       local_tls_type = elf64_x86_64_local_got_tls_type (ibfd);
+      local_tlsdesc_gotent = elf64_x86_64_local_tlsdesc_gotent (ibfd);
       s = htab->sgot;
       srel = htab->srelgot;
-      for (; local_got < end_local_got; ++local_got, ++local_tls_type)
+      for (; local_got < end_local_got;
+	   ++local_got, ++local_tls_type, ++local_tlsdesc_gotent)
 	{
+	  *local_tlsdesc_gotent = (bfd_vma) -1;
 	  if (*local_got > 0)
 	    {
-	      *local_got = s->size;
-	      s->size += GOT_ENTRY_SIZE;
-	      if (*local_tls_type == GOT_TLS_GD)
-		s->size += GOT_ENTRY_SIZE;
+	      if (GOT_TLS_GDESC_P (*local_tls_type))
+		{
+		  *local_tlsdesc_gotent = htab->sgotplt->size
+		    - elf64_x86_64_compute_jump_table_size (htab);
+		  htab->sgotplt->size += 2 * GOT_ENTRY_SIZE;
+		  *local_got = (bfd_vma) -2;
+		}
+	      if (! GOT_TLS_GDESC_P (*local_tls_type)
+		  || GOT_TLS_GD_P (*local_tls_type))
+		{
+		  *local_got = s->size;
+		  s->size += GOT_ENTRY_SIZE;
+		  if (GOT_TLS_GD_P (*local_tls_type))
+		    s->size += GOT_ENTRY_SIZE;
+		}
 	      if (info->shared
-		  || *local_tls_type == GOT_TLS_GD
+		  || GOT_TLS_GD_ANY_P (*local_tls_type)
 		  || *local_tls_type == GOT_TLS_IE)
-		srel->size += sizeof (Elf64_External_Rela);
+		{
+		  if (GOT_TLS_GDESC_P (*local_tls_type))
+		    {
+		      htab->srelplt->size += sizeof (Elf64_External_Rela);
+		      htab->tlsdesc_plt = (bfd_vma) -1;
+		    }
+		  if (! GOT_TLS_GDESC_P (*local_tls_type)
+		      || GOT_TLS_GD_P (*local_tls_type))
+		    srel->size += sizeof (Elf64_External_Rela);
+		}
 	    }
 	  else
 	    *local_got = (bfd_vma) -1;
@@ -1656,6 +1767,27 @@ elf64_x86_64_size_dynamic_sections (bfd 
      sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
 
+  /* For every jump slot reserved in the sgotplt, reloc_count is
+     incremented.  However, when we reserve space for TLS descriptors,
+     it's not incremented, so in order to compute the space reserved
+     for them, it suffices to multiply the reloc count by the jump
+     slot size.  */
+  if (htab->srelplt)
+    htab->sgotplt_jump_table_size
+      = elf64_x86_64_compute_jump_table_size (htab);
+
+  if (htab->tlsdesc_plt)
+    {
+      htab->tlsdesc_got = htab->sgot->size;
+      htab->sgot->size += GOT_ENTRY_SIZE;
+      /* Reserve room for the initial entry.
+	 FIXME: we could probably do away with it in this case.  */
+      if (htab->splt->size == 0)
+	htab->splt->size += PLT_ENTRY_SIZE;
+      htab->tlsdesc_plt = htab->splt->size;
+      htab->splt->size += PLT_ENTRY_SIZE;
+    }
+
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
   relocs = FALSE;
@@ -1679,7 +1811,8 @@ elf64_x86_64_size_dynamic_sections (bfd 
 
 	  /* We use the reloc_count field as a counter if we need
 	     to copy relocs into the output file.  */
-	  s->reloc_count = 0;
+	  if (s != htab->srelplt)
+	    s->reloc_count = 0;
 	}
       else
 	{
@@ -1739,6 +1872,11 @@ elf64_x86_64_size_dynamic_sections (bfd 
 	      || !add_dynamic_entry (DT_PLTREL, DT_RELA)
 	      || !add_dynamic_entry (DT_JMPREL, 0))
 	    return FALSE;
+
+	  if (htab->tlsdesc_plt
+	      && (!add_dynamic_entry (DT_TLSDESC_PLT, 0)
+		  || !add_dynamic_entry (DT_TLSDESC_GOT, 0)))
+	    return FALSE;
 	}
 
       if (relocs)
@@ -1766,6 +1904,41 @@ elf64_x86_64_size_dynamic_sections (bfd 
   return TRUE;
 }
 
+static bfd_boolean
+elf64_x86_64_always_size_sections (bfd *output_bfd,
+				   struct bfd_link_info *info)
+{
+  asection *tls_sec = elf_hash_table (info)->tls_sec;
+
+  if (tls_sec)
+    {
+      struct elf_link_hash_entry *tlsbase;
+
+      tlsbase = elf_link_hash_lookup (elf_hash_table (info),
+				      "_TLS_MODULE_BASE_",
+				      FALSE, FALSE, FALSE);
+
+      if (tlsbase && tlsbase->type == STT_TLS)
+	{
+	  struct bfd_link_hash_entry *bh = NULL;
+	  const struct elf_backend_data *bed
+	    = get_elf_backend_data (output_bfd);
+
+	  if (!(_bfd_generic_link_add_one_symbol
+		(info, output_bfd, "_TLS_MODULE_BASE_", BSF_LOCAL,
+		 tls_sec, 0, NULL, FALSE,
+		 bed->collect, &bh)))
+	    return FALSE;
+	  tlsbase = (struct elf_link_hash_entry *)bh;
+	  tlsbase->def_regular = 1;
+	  tlsbase->other = STV_HIDDEN;
+	  (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE);
+	}
+    }
+
+  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.  */
@@ -1824,6 +1997,7 @@ elf64_x86_64_relocate_section (bfd *outp
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
   bfd_vma *local_got_offsets;
+  bfd_vma *local_tlsdesc_gotents;
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
 
@@ -1834,6 +2008,7 @@ elf64_x86_64_relocate_section (bfd *outp
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (input_bfd);
   local_got_offsets = elf_local_got_offsets (input_bfd);
+  local_tlsdesc_gotents = elf64_x86_64_local_tlsdesc_gotent (input_bfd);
 
   rel = relocs;
   relend = relocs + input_section->reloc_count;
@@ -1845,7 +2020,7 @@ elf64_x86_64_relocate_section (bfd *outp
       struct elf_link_hash_entry *h;
       Elf_Internal_Sym *sym;
       asection *sec;
-      bfd_vma off;
+      bfd_vma off, offplt;
       bfd_vma relocation;
       bfd_boolean unresolved_reloc;
       bfd_reloc_status_type r;
@@ -2204,6 +2379,8 @@ elf64_x86_64_relocate_section (bfd *outp
 	  break;
 
 	case R_X86_64_TLSGD:
+	case R_X86_64_GOTPC32_TLSDESC:
+	case R_X86_64_TLSDESC_CALL:
 	case R_X86_64_GOTTPOFF:
 	  r_type = elf64_x86_64_tls_transition (info, r_type, h == NULL);
 	  tls_type = GOT_UNKNOWN;
@@ -2215,7 +2392,9 @@ elf64_x86_64_relocate_section (bfd *outp
 	      if (!info->shared && h->dynindx == -1 && tls_type == GOT_TLS_IE)
 		r_type = R_X86_64_TPOFF32;
 	    }
-	  if (r_type == R_X86_64_TLSGD)
+	  if (r_type == R_X86_64_TLSGD
+	      || r_type == R_X86_64_GOTPC32_TLSDESC
+	      || r_type == R_X86_64_TLSDESC_CALL)
 	    {
 	      if (tls_type == GOT_TLS_IE)
 		r_type = R_X86_64_GOTTPOFF;
@@ -2257,6 +2436,67 @@ elf64_x86_64_relocate_section (bfd *outp
 		  rel++;
 		  continue;
 		}
+	      else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC)
+		{
+		  /* GDesc -> LE transition.
+		     It's originally something like:
+		     leaq x@tlsdesc(%rip), %rax
+
+		     Change it to:
+		     movl $x@tpoff, %rax
+		     
+		     Registers other than %rax may be set up here.  */
+		  
+		  unsigned int val, type, type2;
+		  bfd_vma roff;
+
+		  /* First, make sure it's a leaq adding rip to a
+		     32-bit offset into any register, although it's
+		     probably almost always going to be rax.  */
+		  roff = rel->r_offset;
+		  BFD_ASSERT (roff >= 3);
+		  type = bfd_get_8 (input_bfd, contents + roff - 3);
+		  BFD_ASSERT ((type & 0xfb) == 0x48);
+		  type2 = bfd_get_8 (input_bfd, contents + roff - 2);
+		  BFD_ASSERT (type2 == 0x8d);
+		  val = bfd_get_8 (input_bfd, contents + roff - 1);
+		  BFD_ASSERT ((val & 0xc7) == 0x05);
+		  BFD_ASSERT (roff + 4 <= input_section->size);
+
+		  /* Now modify the instruction as appropriate.  */
+		  bfd_put_8 (output_bfd, 0x48 | ((type >> 2) & 1),
+			     contents + roff - 3);
+		  bfd_put_8 (output_bfd, 0xc7, contents + roff - 2);
+		  bfd_put_8 (output_bfd, 0xc0 | ((val >> 3) & 7),
+			     contents + roff - 1);
+		  bfd_put_32 (output_bfd, tpoff (info, relocation),
+			      contents + roff);
+		  continue;
+		}
+	      else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSDESC_CALL)
+		{
+		  /* GDesc -> LE transition.
+		     It's originally:
+		     call *(%rax)
+		     Turn it into:
+		     rex64 nop.  */
+		  
+		  unsigned int val, type;
+		  bfd_vma roff;
+
+		  /* First, make sure it's a call *(%rax).  */
+		  roff = rel->r_offset;
+		  BFD_ASSERT (roff + 2 <= input_section->size);
+		  type = bfd_get_8 (input_bfd, contents + roff);
+		  BFD_ASSERT (type == 0xff);
+		  val = bfd_get_8 (input_bfd, contents + roff + 1);
+		  BFD_ASSERT (val == 0x10);
+
+		  /* Now modify the instruction as appropriate.  */
+		  bfd_put_8 (output_bfd, 0x48, contents + roff);
+		  bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
+		  continue;
+		}
 	      else
 		{
 		  unsigned int val, type, reg;
@@ -2322,13 +2562,17 @@ elf64_x86_64_relocate_section (bfd *outp
 	    abort ();
 
 	  if (h != NULL)
-	    off = h->got.offset;
+	    {
+	      off = h->got.offset;
+	      offplt = elf64_x86_64_hash_entry (h)->tlsdesc_got;
+	    }
 	  else
 	    {
 	      if (local_got_offsets == NULL)
 		abort ();
 
 	      off = local_got_offsets[r_symndx];
+	      offplt = local_tlsdesc_gotents[r_symndx];
 	    }
 
 	  if ((off & 1) != 0)
@@ -2338,30 +2582,61 @@ elf64_x86_64_relocate_section (bfd *outp
 	      Elf_Internal_Rela outrel;
 	      bfd_byte *loc;
 	      int dr_type, indx;
+	      asection *sreloc;
 
 	      if (htab->srelgot == NULL)
 		abort ();
 
+	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
+
+	      if (GOT_TLS_GDESC_P (tls_type))
+		{
+		  outrel.r_info = ELF64_R_INFO (indx, R_X86_64_TLSDESC);
+		  BFD_ASSERT (htab->sgotplt_jump_table_size + offplt
+			      + 2 * GOT_ENTRY_SIZE <= htab->sgotplt->size);
+		  outrel.r_offset = (htab->sgotplt->output_section->vma
+				     + htab->sgotplt->output_offset
+				     + offplt
+				     + htab->sgotplt_jump_table_size);
+		  sreloc = htab->srelplt;
+		  loc = sreloc->contents;
+		  loc += sreloc->reloc_count++
+		    * sizeof (Elf64_External_Rela);
+		  BFD_ASSERT (loc + sizeof (Elf64_External_Rela)
+			      <= sreloc->contents + sreloc->size);
+		  if (indx == 0)
+		    outrel.r_addend = relocation - dtpoff_base (info);
+		  else
+		    outrel.r_addend = 0;
+		  bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+		}
+
+	      sreloc = htab->srelgot;
+
 	      outrel.r_offset = (htab->sgot->output_section->vma
 				 + htab->sgot->output_offset + off);
 
-	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
-	      if (r_type == R_X86_64_TLSGD)
+	      if (GOT_TLS_GD_P (tls_type))
 		dr_type = R_X86_64_DTPMOD64;
+	      else if (GOT_TLS_GDESC_P (tls_type))
+		goto dr_done;
 	      else
 		dr_type = R_X86_64_TPOFF64;
 
 	      bfd_put_64 (output_bfd, 0, htab->sgot->contents + off);
 	      outrel.r_addend = 0;
-	      if (dr_type == R_X86_64_TPOFF64 && indx == 0)
+	      if ((dr_type == R_X86_64_TPOFF64
+		   || dr_type == R_X86_64_TLSDESC) && indx == 0)
 		outrel.r_addend = relocation - dtpoff_base (info);
 	      outrel.r_info = ELF64_R_INFO (indx, dr_type);
 
-	      loc = htab->srelgot->contents;
-	      loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela);
+	      loc = sreloc->contents;
+	      loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela);
+	      BFD_ASSERT (loc + sizeof (Elf64_External_Rela)
+			  <= sreloc->contents + sreloc->size);
 	      bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
 
-	      if (r_type == R_X86_64_TLSGD)
+	      if (GOT_TLS_GD_P (tls_type))
 		{
 		  if (indx == 0)
 		    {
@@ -2377,27 +2652,37 @@ elf64_x86_64_relocate_section (bfd *outp
 		      outrel.r_info = ELF64_R_INFO (indx,
 						    R_X86_64_DTPOFF64);
 		      outrel.r_offset += GOT_ENTRY_SIZE;
-		      htab->srelgot->reloc_count++;
+		      sreloc->reloc_count++;
 		      loc += sizeof (Elf64_External_Rela);
+		      BFD_ASSERT (loc + sizeof (Elf64_External_Rela)
+				  <= sreloc->contents + sreloc->size);
 		      bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
 		    }
 		}
 
+	    dr_done:
 	      if (h != NULL)
 		h->got.offset |= 1;
 	      else
 		local_got_offsets[r_symndx] |= 1;
 	    }
 
-	  if (off >= (bfd_vma) -2)
+	  if (off >= (bfd_vma) -2
+	      && ! GOT_TLS_GDESC_P (tls_type))
 	    abort ();
 	  if (r_type == ELF64_R_TYPE (rel->r_info))
 	    {
-	      relocation = htab->sgot->output_section->vma
-			   + htab->sgot->output_offset + off;
+	      if (r_type == R_X86_64_GOTPC32_TLSDESC
+		  || r_type == R_X86_64_TLSDESC_CALL)
+		relocation = htab->sgotplt->output_section->vma
+		  + htab->sgotplt->output_offset
+		  + offplt + htab->sgotplt_jump_table_size;
+	      else
+		relocation = htab->sgot->output_section->vma
+		  + htab->sgot->output_offset + off;
 	      unresolved_reloc = FALSE;
 	    }
-	  else
+	  else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSGD)
 	    {
 	      unsigned int i;
 	      static unsigned char tlsgd[8]
@@ -2437,6 +2722,79 @@ elf64_x86_64_relocate_section (bfd *outp
 	      rel++;
 	      continue;
 	    }
+	  else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC)
+	    {
+	      /* GDesc -> IE transition.
+		 It's originally something like:
+		 leaq x@tlsdesc(%rip), %rax
+
+		 Change it to:
+		 movq x@gottpoff(%rip), %rax # before rex64 nop
+		     
+		 Registers other than %rax may be set up here.  */
+		  
+	      unsigned int val, type, type2;
+	      bfd_vma roff;
+
+	      /* First, make sure it's a leaq adding rip to a 32-bit
+		 offset into any register, although it's probably
+		 almost always going to be rax.  */
+	      roff = rel->r_offset;
+	      BFD_ASSERT (roff >= 3);
+	      type = bfd_get_8 (input_bfd, contents + roff - 3);
+	      BFD_ASSERT ((type & 0xfb) == 0x48);
+	      type2 = bfd_get_8 (input_bfd, contents + roff - 2);
+	      BFD_ASSERT (type2 == 0x8d);
+	      val = bfd_get_8 (input_bfd, contents + roff - 1);
+	      BFD_ASSERT ((val & 0xc7) == 0x05);
+	      BFD_ASSERT (roff + 4 <= input_section->size);
+
+	      /* Now modify the instruction as appropriate.  */
+	      /* To turn a leaq into a movq in the form we use it, it
+		 suffices to change the second byte from 0x8d to 0x8b.
+		 aoliva FIXME: should we decide to keep the leaq, all
+		 we have to do is remove the statement below, and
+		 adjust the relaxation of R_X86_64_TLSDESC_CALL.  */
+	      bfd_put_8 (output_bfd, 0x8b, contents + roff - 2);
+
+	      bfd_put_32 (output_bfd,
+			  htab->sgot->output_section->vma
+			  + htab->sgot->output_offset + off
+			  - rel->r_offset
+			  - input_section->output_section->vma
+			  - input_section->output_offset
+			  - 4,
+			  contents + roff);
+	      continue;
+	    }
+	  else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSDESC_CALL)
+	    {
+	      /* GDesc -> IE transition.
+		 It's originally:
+		 call *(%rax)
+
+		 Change it to:
+		 rex64 nop.  */
+		  
+	      unsigned int val, type;
+	      bfd_vma roff;
+
+	      /* First, make sure it's a call *(%eax).  */
+	      roff = rel->r_offset;
+	      BFD_ASSERT (roff + 2 <= input_section->size);
+	      type = bfd_get_8 (input_bfd, contents + roff);
+	      BFD_ASSERT (type == 0xff);
+	      val = bfd_get_8 (input_bfd, contents + roff + 1);
+	      BFD_ASSERT (val == 0x10);
+
+	      /* Now modify the instruction as appropriate.  */
+	      bfd_put_8 (output_bfd, 0x48, contents + roff);
+	      bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
+
+	      continue;
+	    }
+	  else
+	    BFD_ASSERT (FALSE);
 	  break;
 
 	case R_X86_64_TLSLD:
@@ -2675,7 +3033,7 @@ elf64_x86_64_finish_dynamic_symbol (bfd 
     }
 
   if (h->got.offset != (bfd_vma) -1
-      && elf64_x86_64_hash_entry (h)->tls_type != GOT_TLS_GD
+      && ! GOT_TLS_GD_ANY_P (elf64_x86_64_hash_entry (h)->tls_type)
       && elf64_x86_64_hash_entry (h)->tls_type != GOT_TLS_IE)
     {
       Elf_Internal_Rela rela;
@@ -2830,6 +3188,18 @@ elf64_x86_64_finish_dynamic_sections (bf
 		  dyn.d_un.d_val -= s->size;
 		}
 	      break;
+
+	    case DT_TLSDESC_PLT:
+	      s = htab->splt;
+	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
+		+ htab->tlsdesc_plt;
+	      break;
+	      
+	    case DT_TLSDESC_GOT:
+	      s = htab->sgot;
+	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
+		+ htab->tlsdesc_got;
+	      break;
 	    }
 
 	  bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
@@ -2864,6 +3234,40 @@ elf64_x86_64_finish_dynamic_sections (bf
 
 	  elf_section_data (htab->splt->output_section)->this_hdr.sh_entsize =
 	    PLT_ENTRY_SIZE;
+
+	  if (htab->tlsdesc_plt)
+	    {
+	      bfd_put_64 (output_bfd, (bfd_vma) 0,
+			  htab->sgot->contents + htab->tlsdesc_got);
+
+	      memcpy (htab->splt->contents + htab->tlsdesc_plt,
+		      elf64_x86_64_plt0_entry,
+		      PLT_ENTRY_SIZE);
+
+	      /* Add offset for pushq GOT+8(%rip), since the
+		 instruction uses 6 bytes subtract this value.  */
+	      bfd_put_32 (output_bfd,
+			  (htab->sgotplt->output_section->vma
+			   + htab->sgotplt->output_offset
+			   + 8
+			   - htab->splt->output_section->vma
+			   - htab->splt->output_offset
+			   - htab->tlsdesc_plt
+			   - 6),
+			  htab->splt->contents + htab->tlsdesc_plt + 2);
+	      /* Add offset for jmp *GOT+TDG(%rip), where TGD stands for
+		 htab->tlsdesc_got. The 12 is the offset to the end of
+		 the instruction.  */
+	      bfd_put_32 (output_bfd,
+			  (htab->sgot->output_section->vma
+			   + htab->sgot->output_offset
+			   + htab->tlsdesc_got
+			   - htab->splt->output_section->vma
+			   - htab->splt->output_offset
+			   - htab->tlsdesc_plt
+			   - 12),
+			  htab->splt->contents + htab->tlsdesc_plt + 8);
+	    }
 	}
     }
 
@@ -3135,6 +3539,7 @@ static const struct bfd_elf_special_sect
 #define elf_backend_reloc_type_class	    elf64_x86_64_reloc_type_class
 #define elf_backend_relocate_section	    elf64_x86_64_relocate_section
 #define elf_backend_size_dynamic_sections   elf64_x86_64_size_dynamic_sections
+#define elf_backend_always_size_sections    elf64_x86_64_always_size_sections
 #define elf_backend_plt_sym_val		    elf64_x86_64_plt_sym_val
 #define elf_backend_object_p		    elf64_x86_64_elf_object_p
 #define bfd_elf64_mkobject		    elf64_x86_64_mkobject
Index: bfd/libbfd.h
===================================================================
RCS file: /cvs/uberbaum/./bfd/libbfd.h,v
retrieving revision 1.157
diff -u -p -r1.157 libbfd.h
--- bfd/libbfd.h 8 Sep 2005 12:49:18 -0000 1.157
+++ bfd/libbfd.h 15 Sep 2005 22:38:20 -0000
@@ -1044,6 +1044,9 @@ static const char *const bfd_reloc_code_
   "BFD_RELOC_386_TLS_DTPMOD32",
   "BFD_RELOC_386_TLS_DTPOFF32",
   "BFD_RELOC_386_TLS_TPOFF32",
+  "BFD_RELOC_386_TLS_GOTDESC",
+  "BFD_RELOC_386_TLS_DESC",
+  "BFD_RELOC_386_TLS_DESC_CALL",
   "BFD_RELOC_X86_64_GOT32",
   "BFD_RELOC_X86_64_PLT32",
   "BFD_RELOC_X86_64_COPY",
@@ -1062,6 +1065,9 @@ static const char *const bfd_reloc_code_
   "BFD_RELOC_X86_64_TPOFF32",
   "BFD_RELOC_X86_64_GOTOFF64",
   "BFD_RELOC_X86_64_GOTPC32",
+  "BFD_RELOC_X86_64_GOTPC32_TLSDESC",
+  "BFD_RELOC_X86_64_TLSDESC",
+  "BFD_RELOC_X86_64_TLSDESC_CALL",
   "BFD_RELOC_NS32K_IMM_8",
   "BFD_RELOC_NS32K_IMM_16",
   "BFD_RELOC_NS32K_IMM_32",
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/uberbaum/./bfd/reloc.c,v
retrieving revision 1.138
diff -u -p -r1.138 reloc.c
--- bfd/reloc.c 8 Sep 2005 12:49:19 -0000 1.138
+++ bfd/reloc.c 15 Sep 2005 22:38:22 -0000
@@ -2329,6 +2329,12 @@ ENUMX
   BFD_RELOC_386_TLS_DTPOFF32
 ENUMX
   BFD_RELOC_386_TLS_TPOFF32
+ENUMX
+  BFD_RELOC_386_TLS_GOTDESC
+ENUMX
+  BFD_RELOC_386_TLS_DESC
+ENUMX
+  BFD_RELOC_386_TLS_DESC_CALL
 ENUMDOC
   i386/elf relocations
 
@@ -2368,6 +2374,12 @@ ENUMX
   BFD_RELOC_X86_64_GOTOFF64
 ENUMX
   BFD_RELOC_X86_64_GOTPC32
+ENUMX
+  BFD_RELOC_X86_64_GOTPC32_TLSDESC
+ENUMX
+  BFD_RELOC_X86_64_TLSDESC
+ENUMX
+  BFD_RELOC_X86_64_TLSDESC_CALL
 ENUMDOC
   x86-64/elf relocations
 
Index: binutils/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Introduce TLS descriptors for i386 and x86_64.
	* readelf.c (get_dynamic_type): Handle DT_TLSDESC_GOT and
	DT_TLSDESC_PLT.

Index: binutils/readelf.c
===================================================================
RCS file: /cvs/uberbaum/./binutils/readelf.c,v
retrieving revision 1.315
diff -u -p -r1.315 readelf.c
--- binutils/readelf.c 9 Sep 2005 13:12:21 -0000 1.315
+++ binutils/readelf.c 15 Sep 2005 22:38:29 -0000
@@ -1632,6 +1632,8 @@ get_dynamic_type (unsigned long type)
 
     case DT_VERSYM:	return "VERSYM";
 
+    case DT_TLSDESC_GOT: return "TLSDESC_GOT";
+    case DT_TLSDESC_PLT: return "TLSDESC_PLT";
     case DT_RELACOUNT:	return "RELACOUNT";
     case DT_RELCOUNT:	return "RELCOUNT";
     case DT_FLAGS_1:	return "FLAGS_1";
Index: gas/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Introduce TLS descriptors for i386 and x86_64.
	* config/tc-i386.c (tc_i386_fix_adjustable): Handle
	BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_386_TLS_DESC_CALL,
	BFD_RELOC_X86_64_GOTPC32_TLSDESC, BFD_RELOC_X86_64_TLSDESC_CALL.
	(optimize_disp): Emit fix up for BFD_RELOC_386_TLS_DESC_CALL and
	BFD_RELOC_X86_64_TLSDESC_CALL immediately, and clear the
	displacement bits.
	(build_modrm_byte): Set up zero modrm for TLS desc calls.
	(lex_got): Handle @tlsdesc and @tlscall.
	(md_apply_fix, tc_gen_reloc): Handle the new relocations.

Index: gas/config/tc-i386.c
===================================================================
RCS file: /cvs/uberbaum/./gas/config/tc-i386.c,v
retrieving revision 1.196
diff -u -p -r1.196 tc-i386.c
--- gas/config/tc-i386.c 14 Sep 2005 06:33:25 -0000 1.196
+++ gas/config/tc-i386.c 15 Sep 2005 22:38:39 -0000
@@ -1326,6 +1326,8 @@ tc_i386_fix_adjustable (fixP)
       || fixP->fx_r_type == BFD_RELOC_386_TLS_GOTIE
       || 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_386_TLS_GOTDESC
+      || fixP->fx_r_type == BFD_RELOC_386_TLS_DESC_CALL
       || 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
@@ -1337,6 +1339,8 @@ tc_i386_fix_adjustable (fixP)
       || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF32
       || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF64
       || fixP->fx_r_type == BFD_RELOC_X86_64_GOTOFF64
+      || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPC32_TLSDESC
+      || fixP->fx_r_type == BFD_RELOC_X86_64_TLSDESC_CALL
       || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
     return 0;
@@ -2177,7 +2181,14 @@ optimize_disp ()
 		&& fits_in_signed_byte (disp))
 	      i.types[op] |= Disp8;
 	  }
-	else
+	else if (i.reloc[op] == BFD_RELOC_386_TLS_DESC_CALL
+		 || i.reloc[op] == BFD_RELOC_X86_64_TLSDESC_CALL)
+	  {
+	    fix_new_exp (frag_now, frag_more (0) - frag_now->fr_literal, 0,
+			 i.op[op].disps, 0, i.reloc[op]);
+	    i.types[op] &= ~Disp;
+	  }
+ 	else
 	  /* We only support 64bit displacement on constants.  */
 	  i.types[op] &= ~Disp64;
       }
@@ -3123,7 +3134,13 @@ build_modrm_byte ()
 		  if ((i.index_reg->reg_flags & RegRex) != 0)
 		    i.rex |= REX_EXTY;
 		}
-	      i.rm.mode = mode_from_disp_size (i.types[op]);
+
+	      if (i.disp_operands
+		  && (i.reloc[op] == BFD_RELOC_386_TLS_DESC_CALL
+		      || i.reloc[op] == BFD_RELOC_X86_64_TLSDESC_CALL))
+		i.rm.mode = 0;
+	      else
+		i.rm.mode = mode_from_disp_size (i.types[op]);
 	    }
 
 	  if (fake_zero_displacement)
@@ -3796,7 +3813,9 @@ lex_got (enum bfd_reloc_code_real *reloc
     { "DTPOFF",   { BFD_RELOC_386_TLS_LDO_32, BFD_RELOC_X86_64_DTPOFF32 }, Imm32|Imm32S|Imm64|Disp32|Disp64 },
     { "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE,  0                         }, 0 },
     { "INDNTPOFF",{ BFD_RELOC_386_TLS_IE,     0                         }, 0 },
-    { "GOT",      { BFD_RELOC_386_GOT32,      BFD_RELOC_X86_64_GOT32    }, Imm32|Imm32S|Disp32 }
+    { "GOT",      { BFD_RELOC_386_GOT32,      BFD_RELOC_X86_64_GOT32    }, Imm32|Imm32S|Disp32 },
+    { "TLSDESC",  { BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_X86_64_GOTPC32_TLSDESC }, Imm32|Imm32S|Disp32 },
+    { "TLSCALL",  { BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_X86_64_TLSDESC_CALL }, Imm32|Imm32S|Disp32 }
   };
   char *cp;
   unsigned int j;
@@ -5006,9 +5025,11 @@ md_apply_fix (fixP, valP, seg)
       case BFD_RELOC_386_TLS_IE_32:
       case BFD_RELOC_386_TLS_IE:
       case BFD_RELOC_386_TLS_GOTIE:
+      case BFD_RELOC_386_TLS_GOTDESC:
       case BFD_RELOC_X86_64_TLSGD:
       case BFD_RELOC_X86_64_TLSLD:
       case BFD_RELOC_X86_64_GOTTPOFF:
+      case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
 	value = 0; /* Fully resolved at runtime.  No addend.  */
 	/* Fallthrough */
       case BFD_RELOC_386_TLS_LE:
@@ -5021,6 +5042,13 @@ md_apply_fix (fixP, valP, seg)
 	S_SET_THREAD_LOCAL (fixP->fx_addsy);
 	break;
 
+      case BFD_RELOC_386_TLS_DESC_CALL:
+      case BFD_RELOC_X86_64_TLSDESC_CALL:
+	value = 0; /* Fully resolved at runtime.  No addend.  */
+	S_SET_THREAD_LOCAL (fixP->fx_addsy);
+	fixP->fx_done = 0;
+	return;
+
       case BFD_RELOC_386_GOT32:
       case BFD_RELOC_X86_64_GOT32:
 	value = 0; /* Fully resolved at runtime.  No addend.  */
@@ -5499,6 +5527,8 @@ tc_gen_reloc (section, fixp)
     case BFD_RELOC_386_TLS_GOTIE:
     case BFD_RELOC_386_TLS_LE_32:
     case BFD_RELOC_386_TLS_LE:
+    case BFD_RELOC_386_TLS_GOTDESC:
+    case BFD_RELOC_386_TLS_DESC_CALL:
     case BFD_RELOC_X86_64_TLSGD:
     case BFD_RELOC_X86_64_TLSLD:
     case BFD_RELOC_X86_64_DTPOFF32:
@@ -5508,6 +5538,8 @@ tc_gen_reloc (section, fixp)
     case BFD_RELOC_X86_64_TPOFF64:
     case BFD_RELOC_X86_64_GOTOFF64:
     case BFD_RELOC_X86_64_GOTPC32:
+    case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
+    case BFD_RELOC_X86_64_TLSDESC_CALL:
     case BFD_RELOC_RVA:
     case BFD_RELOC_VTABLE_ENTRY:
     case BFD_RELOC_VTABLE_INHERIT:
@@ -5602,6 +5634,8 @@ tc_gen_reloc (section, fixp)
 	  case BFD_RELOC_X86_64_TLSGD:
 	  case BFD_RELOC_X86_64_TLSLD:
 	  case BFD_RELOC_X86_64_GOTTPOFF:
+	  case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
+	  case BFD_RELOC_X86_64_TLSDESC_CALL:
 	    rel->addend = fixp->fx_offset - fixp->fx_size;
 	    break;
 	  default:
Index: ld/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* ld-i386/i386.exp: Run on x86_64-*-linux* and amd64-*-linux*.
	Add new tests.
	* ld-i386/pcrel16.d: Add -melf_i386.
	* ld-i386/pcrel8.d: Likewise.
	* ld-i386/tlsbindesc.dd: New.
	* ld-i386/tlsbindesc.rd: New.
	* ld-i386/tlsbindesc.s: New.
	* ld-i386/tlsbindesc.sd: New.
	* ld-i386/tlsbindesc.td: New.
	* ld-i386/tlsdesc.dd: New.
	* ld-i386/tlsdesc.rd: New.
	* ld-i386/tlsdesc.s: New.
	* ld-i386/tlsdesc.sd: New.
	* ld-i386/tlsdesc.td: New.
	* ld-i386/tlsgdesc.dd: New.
	* ld-i386/tlsgdesc.rd: New.
	* ld-i386/tlsgdesc.s: New.
	* ld-x86-64/x86-64.exp: Run new tests.
	* ld-x86-64/tlsbindesc.dd: New.
	* ld-x86-64/tlsbindesc.rd: New.
	* ld-x86-64/tlsbindesc.s: New.
	* ld-x86-64/tlsbindesc.sd: New.
	* ld-x86-64/tlsbindesc.td: New.
	* ld-x86-64/tlsdesc.dd: New.
	* ld-x86-64/tlsdesc.pd: New.
	* ld-x86-64/tlsdesc.rd: New.
	* ld-x86-64/tlsdesc.s: New.
	* ld-x86-64/tlsdesc.sd: New.
	* ld-x86-64/tlsdesc.td: New.
	* ld-x86-64/tlsgdesc.dd: New.
	* ld-x86-64/tlsgdesc.rd: New.
	* ld-x86-64/tlsgdesc.s: New.

Index: ld/testsuite/ld-i386/i386.exp
===================================================================
RCS file: /cvs/uberbaum/./ld/testsuite/ld-i386/i386.exp,v
retrieving revision 1.10
diff -u -p -r1.10 i386.exp
--- ld/testsuite/ld-i386/i386.exp 18 Jul 2005 06:23:40 -0000 1.10
+++ ld/testsuite/ld-i386/i386.exp 15 Sep 2005 22:39:23 -0000
@@ -1,5 +1,5 @@
 # Expect script for ld-i386 tests
-#   Copyright (C) 2002 Free Software Foundation
+#   Copyright (C) 2002, 2005 Free Software Foundation
 #
 # This file is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -22,7 +22,9 @@
 if { !([istarget "i?86-*-elf*"]		
        || ([istarget "i?86-*-linux*"]
 	   && ![istarget "*-*-*aout*"]
-	   && ![istarget "*-*-*oldld*"])) } {
+	   && ![istarget "*-*-*oldld*"])
+       || [istarget "x86_64-*-linux*"]
+       || [istarget "amd64-*-linux*"]) } {
     return
 }
 
@@ -41,6 +43,11 @@ set i386tests {
      {{readelf -Ssrl tlspic.rd} {objdump -drj.text tlspic.dd}
       {objdump -sj.got tlspic.sd} {objdump -sj.tdata tlspic.td}}
       "libtlspic.so"}
+    {"TLS descriptor -fpic -shared transitions" "-shared -melf_i386"
+     "--32" {tlsdesc.s tlspic2.s}
+     {{readelf -Ssrl tlsdesc.rd} {objdump -drj.text tlsdesc.dd}
+      {objdump "-s -j.got -j.got.plt" tlsdesc.sd} {objdump -sj.tdata tlsdesc.td}}
+      "libtlsdesc.so"}
     {"Helper shared library" "-shared -melf_i386"
      "--32" {tlslib.s} {} "libtlslib.so"}
     {"TLS -fpic and -fno-pic exec transitions"
@@ -48,10 +55,19 @@ set i386tests {
      {{readelf -Ssrl tlsbin.rd} {objdump -drj.text tlsbin.dd}
       {objdump -sj.got tlsbin.sd} {objdump -sj.tdata tlsbin.td}}
       "tlsbin"}
+    {"TLS descriptor -fpic and -fno-pic exec transitions"
+     "-melf_i386 tmpdir/libtlslib.so" "--32" {tlsbindesc.s tlsbin.s}
+     {{readelf -Ssrl tlsbindesc.rd} {objdump -drj.text tlsbindesc.dd}
+      {objdump -sj.got tlsbindesc.sd} {objdump -sj.tdata tlsbindesc.td}}
+      "tlsbindesc"}
     {"TLS -fno-pic -shared" "-shared -melf_i386"
      "--32" {tlsnopic1.s tlsnopic2.s}
      {{readelf -Ssrl tlsnopic.rd} {objdump -drj.text tlsnopic.dd}
       {objdump -sj.got tlsnopic.sd}} "libtlsnopic.so"}
+    {"TLS with global dynamic and descriptors"
+	"-shared -melf_i386" "--32" {tlsgdesc.s}
+     {{readelf -Ssrl tlsgdesc.rd} {objdump -drj.text tlsgdesc.dd}}
+      "libtlsgdesc.so"}
     {"TLS in debug sections" "-melf_i386"
      "--32" {tlsg.s}
      {{objdump -sj.debug_foobar tlsg.sd}} "tlsg"}
Index: ld/testsuite/ld-i386/pcrel16.d
===================================================================
RCS file: /cvs/uberbaum/./ld/testsuite/ld-i386/pcrel16.d,v
retrieving revision 1.2
diff -u -p -r1.2 pcrel16.d
--- ld/testsuite/ld-i386/pcrel16.d 3 Aug 2005 16:30:34 -0000 1.2
+++ ld/testsuite/ld-i386/pcrel16.d 15 Sep 2005 22:39:23 -0000
@@ -1,5 +1,6 @@
 #name: PCREL16 overflow
-#ld: -Ttext 0x0
+#as: --32
+#ld: -melf_i386 -Ttext 0x0
 #objdump: -drj.text -m i8086
 
 .*: +file format elf32-i386
Index: ld/testsuite/ld-i386/pcrel8.d
===================================================================
RCS file: /cvs/uberbaum/./ld/testsuite/ld-i386/pcrel8.d,v
retrieving revision 1.1
diff -u -p -r1.1 pcrel8.d
--- ld/testsuite/ld-i386/pcrel8.d 18 Jul 2005 06:23:40 -0000 1.1
+++ ld/testsuite/ld-i386/pcrel8.d 15 Sep 2005 22:39:23 -0000
@@ -1,3 +1,4 @@
 #name: PCREL8 overflow
-#ld:
+#as: --32
+#ld: -melf_i386
 #error: .*relocation truncated to fit: R_386_PC8 .*
Index: ld/testsuite/ld-i386/tlsbindesc.dd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsbindesc.dd
diff -N ld/testsuite/ld-i386/tlsbindesc.dd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsbindesc.dd 15 Sep 2005 22:39:23 -0000
@@ -0,0 +1,461 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --32
+#ld: -melf_i386 tmpdir/libtlslib.so
+#objdump: -drj.text
+#target: i?86-*-*
+
+# PT_TLS layout is:
+# Offset from	Offset from	Name
+# TCB base	TCB end
+# 0x00		-0xa0		sg1..sg8
+# 0x20		-0x80		sl1..sl8
+# 0x40		-0x60		sh1..sh8
+# 0x60		-0x40		bg1..bg8
+# 0x80		-0x20		bl1..bl8
+
+.*: +file format elf32-i386
+
+Disassembly of section .text:
+
+[0-9a-f]+ <fn2>:
+ [0-9a-f]+:	55[ 	]+push   %ebp
+ [0-9a-f]+:	89 e5[ 	]+mov    %esp,%ebp
+ [0-9a-f]+:	53[ 	]+push   %ebx
+ [0-9a-f]+:	50[ 	]+push   %eax
+ [0-9a-f]+:	e8 00 00 00 00[ 	]+call   [0-9a-f]+ <fn2\+0xa>
+ [0-9a-f]+:	5b[ 	]+pop    %ebx
+ [0-9a-f]+:	81 c3 fa 10 00 00[ 	]+add    \$0x10fa,%ebx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable
+ [0-9a-f]+:	8b 83 f8 ff ff ff[ 	]+mov    0xfffffff8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG1
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable where
+#  the variable is referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 e8 ff ff ff[ 	]+mov    0xffffffe8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable where
+#  the variable is referenced through @gotntpoff too
+ [0-9a-f]+:	8b 83 dc ff ff ff[ 	]+mov    0xffffffdc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG3
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable where
+#  the variable is referenced through @gottpoff and @gotntpoff too
+ [0-9a-f]+:	8b 83 f0 ff ff ff[ 	]+mov    0xfffffff0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG4
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with global variable defined in executable
+ [0-9a-f]+:	65[ 	]+gs
+ [0-9a-f]+:	b8 00 f0 ff ff[ 	]+mov    \$0xfffff000,%eax
+#							sg1
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with local variable defined in executable
+ [0-9a-f]+:	65[ 	]+gs
+ [0-9a-f]+:	b8 20 f0 ff ff[ 	]+mov    \$0xfffff020,%eax
+#							sl1
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with hidden variable defined in executable
+ [0-9a-f]+:	65[ 	]+gs
+ [0-9a-f]+:	b8 40 f0 ff ff[ 	]+mov    \$0xfffff040,%eax
+#							sh1
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD -> LE
+ [0-9a-f]+:	65[ 	]+gs
+ [0-9a-f]+:	b8 00 f0 ff ff[ 	]+mov    \$0xfffff000,%eax
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 90 20 f0 ff ff[ 	]+lea    0xfffff020\(%eax\),%edx
+#							sl1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 24 f0 ff ff[ 	]+lea    0xfffff024\(%eax\),%ecx
+#							sl2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD -> LE against hidden variables
+ [0-9a-f]+:	65[ 	]+gs
+ [0-9a-f]+:	b8 00 f0 ff ff[ 	]+mov    \$0xfffff000,%eax
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 90 40 f0 ff ff[ 	]+lea    0xfffff040\(%eax\),%edx
+#							sh1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 44 f0 ff ff[ 	]+lea    0xfffff044\(%eax\),%ecx
+#							sh2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b e8 ff ff ff[ 	]+sub    0xffffffe8\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	sG2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 ec ff ff ff[ 	]+sub    0xffffffec\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b dc ff ff ff[ 	]+add    0xffffffdc\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sG3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 f0 ff ff ff[ 	]+add    0xfffffff0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against global var defined in exec
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 e9 00 10 00 00[ 	]+sub    \$0x1000,%ecx
+#							sg1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE -> LE against local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c0 20 f0 ff ff[ 	]+add    \$0xfffff020,%eax
+#							sl1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against hidden var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 e9 c0 0f 00 00[ 	]+sub    \$0xfc0,%ecx
+#							sh1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  Direct access through %gs
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	8b 8b e0 ff ff ff[ 	]+mov    0xffffffe0\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sG5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 11[ 	]+mov    %gs:\(%ecx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE->LE against local var
+ [0-9a-f]+:	c7 c0 30 f0 ff ff[ 	]+mov    \$0xfffff030,%eax
+#							sl5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 10[ 	]+mov    %gs:\(%eax\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE->LE against hidden var
+ [0-9a-f]+:	c7 c2 50 f0 ff ff[ 	]+mov    \$0xfffff050,%edx
+#							sh5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 12[ 	]+mov    %gs:\(%edx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 5d fc[ 	]+mov    0xfffffffc\(%ebp\),%ebx
+ [0-9a-f]+:	c9[ 	]+leave *
+ [0-9a-f]+:	c3[ 	]+ret *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+
+[0-9a-f]+ <_start>:
+ [0-9a-f]+:	55[ 	]+push   %ebp
+ [0-9a-f]+:	89 e5[ 	]+mov    %esp,%ebp
+ [0-9a-f]+:	e8 00 00 00 00[ 	]+call   [0-9a-f]+ <_start\+0x8>
+ [0-9a-f]+:	59[ 	]+pop    %ecx
+ [0-9a-f]+:	81 c1 a4 0f 00 00[ 	]+add    \$0xfa4,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 91 f4 ff ff ff[ 	]+sub    0xfffffff4\(%ecx\),%edx
+#				->R_386_TLS_TPOFF32	sG6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 05 e8 a0 04 08[ 	]+add    0x804a0e8,%eax
+#				->R_386_TLS_TPOFF	sG7
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff direct %gs access IE against global var
+ [0-9a-f]+:	8b 15 00 a1 04 08[ 	]+mov    0x804a100,%edx
+#				->R_386_TLS_TPOFF	sG8
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 02[ 	]+mov    %gs:\(%edx\),%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against global var defined in exec
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 ea 8c 0f 00 00[ 	]+sub    \$0xf8c,%edx
+#							bg6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff IE -> LE against global var defined in exec
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c0 78 f0 ff ff[ 	]+add    \$0xfffff078,%eax
+#							bg7
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff direct %gs access IE -> LE against global var defined
+#  in exec
+ [0-9a-f]+:	c7 c2 7c f0 ff ff[ 	]+mov    \$0xfffff07c,%edx
+#							bg8
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 02[ 	]+mov    %gs:\(%edx\),%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against local var
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 ea 6c 0f 00 00[ 	]+sub    \$0xf6c,%edx
+#							bl6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff IE -> LE against local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c0 98 f0 ff ff[ 	]+add    \$0xfffff098,%eax
+#							bl7
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff direct %gs access IE -> LE against local var
+ [0-9a-f]+:	c7 c2 9c f0 ff ff[ 	]+mov    \$0xfffff09c,%edx
+#							bl8
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 02[ 	]+mov    %gs:\(%edx\),%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against hidden but not local var
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 ea ac 0f 00 00[ 	]+sub    \$0xfac,%edx
+#							sh6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff IE -> LE against hidden but not local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c0 58 f0 ff ff[ 	]+add    \$0xfffff058,%eax
+#							sh7
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff direct %gs access IE -> LE against hidden but not
+#  local var
+ [0-9a-f]+:	c7 c2 5c f0 ff ff[ 	]+mov    \$0xfffff05c,%edx
+#							sh8
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 02[ 	]+mov    %gs:\(%edx\),%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @tpoff, global var defined in exec
+ [0-9a-f]+:	ba 00 10 00 00[ 	]+mov    \$0x1000,%edx
+#							sg1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	29 d0[ 	]+sub    %edx,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @tpoff, local var
+ [0-9a-f]+:	b8 7f 0f 00 00[ 	]+mov    \$0xf7f,%eax
+#							bl1+1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	29 c2[ 	]+sub    %eax,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @tpoff, hidden var defined in exec
+ [0-9a-f]+:	b8 bd 0f 00 00[ 	]+mov    \$0xfbd,%eax
+#							sh1+3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	29 c2[ 	]+sub    %eax,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, global var defined in exec
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 90 04 f0 ff ff[ 	]+lea    0xfffff004\(%eax\),%edx
+#							sg2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, local var, non-canonical sequence
+ [0-9a-f]+:	b8 86 f0 ff ff[ 	]+mov    \$0xfffff086,%eax
+#							bl2+2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	01 c2[ 	]+add    %eax,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, hidden var defined in exec, non-canonical sequence
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c2 45 f0 ff ff[ 	]+add    \$0xfffff045,%edx
+#							sh2+1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, global var defined in exec
+ [0-9a-f]+:	65 a1 08 f0 ff ff[ 	]+mov    %gs:0xfffff008,%eax
+#							sg3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, local var
+ [0-9a-f]+:	65 8b 15 8b f0 ff ff[ 	]+mov    %gs:0xfffff08b,%edx
+#							bl3+3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, hidden var defined in exec
+ [0-9a-f]+:	65 8b 15 49 f0 ff ff[ 	]+mov    %gs:0xfffff049,%edx
+#							sh3+1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 5d fc[ 	]+mov    0xfffffffc\(%ebp\),%ebx
+ [0-9a-f]+:	c9[ 	]+leave *
+ [0-9a-f]+:	c3[ 	]+ret *
Index: ld/testsuite/ld-i386/tlsbindesc.rd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsbindesc.rd
diff -N ld/testsuite/ld-i386/tlsbindesc.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsbindesc.rd 15 Sep 2005 22:39:23 -0000
@@ -0,0 +1,154 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --32
+#ld: -melf_i386 tmpdir/libtlslib.so
+#readelf: -Ssrl
+#target: i?86-*-*
+
+There are 15 section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+  \[ 1\] \.interp +.*
+  \[ 2\] \.hash +.*
+  \[ 3\] \.dynsym +.*
+  \[ 4\] \.dynstr +.*
+  \[ 5\] \.rel.dyn +.*
+  \[ 6\] \.text +PROGBITS +0+8049000 .*
+  \[ 7\] \.tdata +PROGBITS +0+804a000 [0-9a-f]+ 000060 00 WAT  0   0 4096
+  \[ 8\] \.tbss +NOBITS +[0-9a-f]+ [0-9a-f]+ 000040 00 WAT  0   0  1
+  \[ 9\] \.dynamic +DYNAMIC +0+804a060 .*
+  \[10\] \.got +PROGBITS +0+804a0e0 .*
+  \[11\] \.got\.plt +PROGBITS +0+804a104 .*
+  \[12\] \.shstrtab +.*
+  \[13\] \.symtab +.*
+  \[14\] \.strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x8049158
+There are 6 program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  PHDR.*
+  INTERP.*
+.*Requesting program interpreter.*
+  LOAD.*
+  LOAD.*
+  DYNAMIC.*
+  TLS +0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x0+60 0x0+a0 R +0x1000
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +
+   01 +.interp *
+   02 +.interp .hash .dynsym .dynstr .rel.dyn .text *
+   03 +.tdata .dynamic .got .got.plt *
+   04 +.dynamic *
+   05 +.tdata .tbss *
+
+Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 9 entries:
+ Offset +Info +Type +Sym.Value +Sym. Name
+0+804a0e0  0000010e R_386_TLS_TPOFF +0+ +sG3
+0+804a0e4  0000020e R_386_TLS_TPOFF +0+ +sG5
+0+804a0e8  0000030e R_386_TLS_TPOFF +0+ +sG7
+0+804a0ec  00000425 R_386_TLS_TPOFF32 0+ +sG2
+0+804a0f0  00000525 R_386_TLS_TPOFF32 0+ +sG4
+0+804a0f4  0000050e R_386_TLS_TPOFF +0+ +sG4
+0+804a0f8  00000725 R_386_TLS_TPOFF32 0+ +sG6
+0+804a0fc  00000825 R_386_TLS_TPOFF32 0+ +sG1
+0+804a100  00000b0e R_386_TLS_TPOFF +0+ +sG8
+
+Symbol table '.dynsym' contains 12 entries:
+ +Num: +Value  Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG7
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG8
+
+Symbol table '.symtab' contains 71 entries:
+ +Num: +Value  Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +[0-9]+: 00000020 +0 TLS +LOCAL  DEFAULT +7 sl1
+ +[0-9]+: 00000024 +0 TLS +LOCAL  DEFAULT +7 sl2
+ +[0-9]+: 00000028 +0 TLS +LOCAL  DEFAULT +7 sl3
+ +[0-9]+: 0000002c +0 TLS +LOCAL  DEFAULT +7 sl4
+ +[0-9]+: 00000030 +0 TLS +LOCAL  DEFAULT +7 sl5
+ +[0-9]+: 00000034 +0 TLS +LOCAL  DEFAULT +7 sl6
+ +[0-9]+: 00000038 +0 TLS +LOCAL  DEFAULT +7 sl7
+ +[0-9]+: 0000003c +0 TLS +LOCAL  DEFAULT +7 sl8
+ +[0-9]+: 00000080 +0 TLS +LOCAL  DEFAULT +8 bl1
+ +[0-9]+: 00000084 +0 TLS +LOCAL  DEFAULT +8 bl2
+ +[0-9]+: 00000088 +0 TLS +LOCAL  DEFAULT +8 bl3
+ +[0-9]+: 0000008c +0 TLS +LOCAL  DEFAULT +8 bl4
+ +[0-9]+: 00000090 +0 TLS +LOCAL  DEFAULT +8 bl5
+ +[0-9]+: 00000094 +0 TLS +LOCAL  DEFAULT +8 bl6
+ +[0-9]+: 00000098 +0 TLS +LOCAL  DEFAULT +8 bl7
+ +[0-9]+: 0000009c +0 TLS +LOCAL  DEFAULT +8 bl8
+ +[0-9]+: 00000000 +0 TLS +LOCAL  HIDDEN +7 _TLS_MODULE_BASE_
+ +[0-9]+: 0+804a060 +0 OBJECT  LOCAL  HIDDEN    9 _DYNAMIC
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN   11 _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0000001c +0 TLS +GLOBAL DEFAULT +7 sg8
+ +[0-9]+: 0000007c +0 TLS +GLOBAL DEFAULT +8 bg8
+ +[0-9]+: 00000074 +0 TLS +GLOBAL DEFAULT +8 bg6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 00000068 +0 TLS +GLOBAL DEFAULT +8 bg3
+ +[0-9]+: 00000008 +0 TLS +GLOBAL DEFAULT +7 sg3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG7
+ +[0-9]+: 00000048 +0 TLS +GLOBAL HIDDEN +7 sh3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0000000c +0 TLS +GLOBAL DEFAULT +7 sg4
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: 00000010 +0 TLS +GLOBAL DEFAULT +7 sg5
+ +[0-9]+: 00000070 +0 TLS +GLOBAL DEFAULT +8 bg5
+ +[0-9]+: 00000058 +0 TLS +GLOBAL HIDDEN +7 sh7
+ +[0-9]+: 0000005c +0 TLS +GLOBAL HIDDEN +7 sh8
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1
+ +[0-9]+: 0+8049158 +0 FUNC +GLOBAL DEFAULT +6 _start
+ +[0-9]+: 0000004c +0 TLS +GLOBAL HIDDEN +7 sh4
+ +[0-9]+: 00000078 +0 TLS +GLOBAL DEFAULT +8 bg7
+ +[0-9]+: 00000050 +0 TLS +GLOBAL HIDDEN +7 sh5
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: 0+8049000 +0 FUNC +GLOBAL DEFAULT +6 fn2
+ +[0-9]+: 00000004 +0 TLS +GLOBAL DEFAULT +7 sg2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: 00000040 +0 TLS +GLOBAL HIDDEN +7 sh1
+ +[0-9]+: 00000014 +0 TLS +GLOBAL DEFAULT +7 sg6
+ +[0-9]+: 00000018 +0 TLS +GLOBAL DEFAULT +7 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 00000044 +0 TLS +GLOBAL HIDDEN +7 sh2
+ +[0-9]+: 00000054 +0 TLS +GLOBAL HIDDEN +7 sh6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG8
+ +[0-9]+: 00000064 +0 TLS +GLOBAL DEFAULT +8 bg2
+ +[0-9]+: 00000060 +0 TLS +GLOBAL DEFAULT +8 bg1
+ +[0-9]+: 0000006c +0 TLS +GLOBAL DEFAULT +8 bg4
Index: ld/testsuite/ld-i386/tlsbindesc.s
===================================================================
RCS file: ld/testsuite/ld-i386/tlsbindesc.s
diff -N ld/testsuite/ld-i386/tlsbindesc.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsbindesc.s 15 Sep 2005 22:39:23 -0000
@@ -0,0 +1,167 @@
+	/* Force .got aligned to 4K, so it very likely gets at 0x804a100
+	   (0x60 bytes .tdata and 0xa0 bytes .dynamic)  */
+	.section ".tdata", "awT", @progbits
+	.balign	4096
+	.globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8
+	.globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+	.hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	/* Force .text aligned to 4K, so it very likely gets at 0x8049000.  */
+	.text
+	.balign	4096
+	.globl	fn2
+	.type	fn2,@function
+fn2:
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	pushl	%eax
+	call	1f
+1:	popl	%ebx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable */
+	leal	sG1@tlsdesc(%ebx), %eax
+	call	*sG1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through @gottpoff too */
+	leal	sG2@tlsdesc(%ebx), %eax
+	call	*sG2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through @gotntpoff too */
+	leal	sG3@tlsdesc(%ebx), %eax
+	call	*sG3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through @gottpoff and @gotntpoff too */
+	leal	sG4@tlsdesc(%ebx), %eax
+	call	*sG4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with global variable defined in executable */
+	leal	sg1@tlsdesc(%ebx), %eax
+	call	*sg1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with local variable defined in executable */
+	leal	sl1@tlsdesc(%ebx), %eax
+	call	*sl1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with hidden variable defined in executable */
+	leal	sh1@tlsdesc(%ebx), %eax
+	call	*sh1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* LD -> LE */
+	leal	_TLS_MODULE_BASE_@tlsdesc(%ebx), %eax
+	call	*_TLS_MODULE_BASE_@tlscall(%eax)
+	nop;nop
+	leal	sl1@dtpoff(%eax), %edx
+	nop;nop
+	leal	sl2@dtpoff(%eax), %ecx
+	nop;nop;nop;nop
+
+	/* LD -> LE against hidden variables */
+	leal	_TLS_MODULE_BASE_@tlsdesc(%ebx), %eax
+	call	*_TLS_MODULE_BASE_@tlscall(%eax)
+	nop;nop
+	leal	sh1@dtpoff(%eax), %edx
+	nop;nop
+	leal	sh2@dtpoff(%eax), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sG2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sG4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sG3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sG4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE -> LE against global var defined in exec */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sg1@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE -> LE against local var */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sl1@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE -> LE against hidden var */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sh1@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* Direct access through %gs  */
+
+	/* @gotntpoff IE against global var  */
+	movl	sG5@gotntpoff(%ebx), %ecx
+	nop;nop
+	movl	%gs:(%ecx), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE->LE against local var  */
+	movl	sl5@gotntpoff(%ebx), %eax
+	nop;nop
+	movl	%gs:(%eax), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE->LE against hidden var  */
+	movl	sh5@gotntpoff(%ebx), %edx
+	nop;nop
+	movl	%gs:(%edx), %edx
+	nop;nop;nop;nop
+
+	movl    -4(%ebp), %ebx
+	leave
+	ret
Index: ld/testsuite/ld-i386/tlsbindesc.sd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsbindesc.sd
diff -N ld/testsuite/ld-i386/tlsbindesc.sd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsbindesc.sd 15 Sep 2005 22:39:23 -0000
@@ -0,0 +1,13 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --32
+#ld: -melf_i386 tmpdir/libtlslib.so
+#objdump: -sj.got
+#target: i?86-*-*
+
+.*:     file format elf32-i386
+
+Contents of section \.got:
+ 804a0e0 [0-9a-f]+ 00000000 00000000 [0-9a-f]+  .*
+ 804a0f0 00000000 00000000 00000000 00000000  .*
+ 804a100 00000000  +.*
Index: ld/testsuite/ld-i386/tlsbindesc.td
===================================================================
RCS file: ld/testsuite/ld-i386/tlsbindesc.td
diff -N ld/testsuite/ld-i386/tlsbindesc.td
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsbindesc.td 15 Sep 2005 22:39:23 -0000
@@ -0,0 +1,16 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --32
+#ld: -melf_i386 tmpdir/libtlslib.so
+#objdump: -sj.tdata
+#target: i?86-*-*
+
+.*:     file format elf32-i386
+
+Contents of section \.tdata:
+ 804a000 11000000 12000000 13000000 14000000  .*
+ 804a010 15000000 16000000 17000000 18000000  .*
+ 804a020 41000000 42000000 43000000 44000000  .*
+ 804a030 45000000 46000000 47000000 48000000  .*
+ 804a040 01010000 02010000 03010000 04010000  .*
+ 804a050 05010000 06010000 07010000 08010000  .*
Index: ld/testsuite/ld-i386/tlsdesc.dd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsdesc.dd
diff -N ld/testsuite/ld-i386/tlsdesc.dd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsdesc.dd 15 Sep 2005 22:39:23 -0000
@@ -0,0 +1,391 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --32
+#ld: -shared -melf_i386
+#objdump: -drj.text
+#target: i?86-*-*
+
+.*: +file format elf32-i386
+
+Disassembly of section .text:
+
+[0-9a-f]+ <fn1>:
+ [0-9a-f]+:	55[ 	]+push   %ebp
+ [0-9a-f]+:	89 e5[ 	]+mov    %esp,%ebp
+ [0-9a-f]+:	53[ 	]+push   %ebx
+ [0-9a-f]+:	50[ 	]+push   %eax
+ [0-9a-f]+:	e8 00 00 00 00[ 	]+call   [0-9a-f]+ <fn1\+0xa>
+ [0-9a-f]+:	5b[ 	]+pop    %ebx
+ [0-9a-f]+:	81 c3 9a 13 00 00[ 	]+add    \$0x[0-9a-f]+,%ebx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GDesc
+ [0-9a-f]+:	8d 83 24 00 00 00[ 	]+lea    0x24\(%ebx\),%eax
+#				->R_386_TLS_DESC	sg1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 f8 ff ff ff[ 	]+mov    0xfffffff8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sg2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gotntpoff too
+ [0-9a-f]+:	8b 83 c4 ff ff ff[ 	]+mov    0xffffffc4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sg3
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gottpoff and
+ [0-9a-f]+:	8b 83 d4 ff ff ff[ 	]+mov    0xffffffd4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sg4
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD against local variable
+ [0-9a-f]+:	8d 83 0c 00 00 00[ 	]+lea    0xc\(%ebx\),%eax
+#				->R_386_TLS_DESC	sl1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against local variable referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 b0 ff ff ff[ 	]+mov    0xffffffb0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sl2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against local variable referenced through @gotntpoff
+ [0-9a-f]+:	8b 83 b4 ff ff ff[ 	]+mov    0xffffffb4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sl3
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against local variable referenced through @gottpoff and
+ [0-9a-f]+:	8b 83 bc ff ff ff[ 	]+mov    0xffffffbc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sl4
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD against hidden and local variable
+ [0-9a-f]+:	8d 83 2c 00 00 00[ 	]+lea    0x2c\(%ebx\),%eax
+#				->R_386_TLS_DESC	sh1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden and local variable referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 fc ff ff ff[ 	]+mov    0xfffffffc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sh2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden and local variable referenced through @gotntpoff too
+ [0-9a-f]+:	8b 83 c8 ff ff ff[ 	]+mov    0xffffffc8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sh3
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden and local variable referenced through @gottpoff and @gotntpoff too
+ [0-9a-f]+:	8b 83 e8 ff ff ff[ 	]+mov    0xffffffe8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sh4
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD against hidden but not local variable
+ [0-9a-f]+:	8d 83 14 00 00 00[ 	]+lea    0x14\(%ebx\),%eax
+#				->R_386_TLS_DESC	sH1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden but not local variable referenced through
+ [0-9a-f]+:	8b 83 cc ff ff ff[ 	]+mov    0xffffffcc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sH2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden but not local variable referenced through
+ [0-9a-f]+:	8b 83 ec ff ff ff[ 	]+mov    0xffffffec\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sH3
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden but not local variable referenced through
+ [0-9a-f]+:	8b 83 e0 ff ff ff[ 	]+mov    0xffffffe0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sH4
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD
+ [0-9a-f]+:	8d 83 1c 00 00 00[ 	]+lea    0x1c\(%ebx\),%eax
+#				->R_386_TLS_DESC	_TLS_MODULE_BASE_
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 90 20 00 00 00[ 	]+lea    0x20\(%eax\),%edx
+#							sl1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 26 00 00 00[ 	]+lea    0x26\(%eax\),%ecx
+#							sl2+2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD against hidden and local variables
+ [0-9a-f]+:	8d 90 40 00 00 00[ 	]+lea    0x40\(%eax\),%edx
+#							sh1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 47 00 00 00[ 	]+lea    0x47\(%eax\),%ecx
+#							sh2+3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD against hidden but not local variables
+ [0-9a-f]+:	8d 90 60 00 00 00[ 	]+lea    0x60\(%eax\),%edx
+#							sH1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 65 00 00 00[ 	]+lea    0x65\(%eax\),%ecx
+#							sH2+1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b f8 ff ff ff[ 	]+sub    0xfffffff8\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	sg2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 d0 ff ff ff[ 	]+sub    0xffffffd0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sg4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b c4 ff ff ff[ 	]+add    0xffffffc4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sg3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 d4 ff ff ff[ 	]+add    0xffffffd4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sg4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b b0 ff ff ff[ 	]+sub    0xffffffb0\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	[0xdcffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 b8 ff ff ff[ 	]+sub    0xffffffb8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	[0xd4ffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b b4 ff ff ff[ 	]+add    0xffffffb4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	[0x28000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 bc ff ff ff[ 	]+add    0xffffffbc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	[0x2c000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against hidden and local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b fc ff ff ff[ 	]+sub    0xfffffffc\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	[0xbcffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against hidden and local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 e4 ff ff ff[ 	]+sub    0xffffffe4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	[0xb4ffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden and local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b c8 ff ff ff[ 	]+add    0xffffffc8\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	[0x48000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden and local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 e8 ff ff ff[ 	]+add    0xffffffe8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	[0x4c000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against hidden but not local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b cc ff ff ff[ 	]+sub    0xffffffcc\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	[0x9cffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against hidden but not local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 dc ff ff ff[ 	]+sub    0xffffffdc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	[0x94ffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden but not local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b ec ff ff ff[ 	]+add    0xffffffec\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	[0x68000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden but not local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 e0 ff ff ff[ 	]+add    0xffffffe0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	[0x6c000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  Direct access through %gs
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	8b 8b d8 ff ff ff[ 	]+mov    0xffffffd8\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sg5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 11[ 	]+mov    %gs:\(%ecx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against local var
+ [0-9a-f]+:	8b 83 c0 ff ff ff[ 	]+mov    0xffffffc0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	[0x30000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 10[ 	]+mov    %gs:\(%eax\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden and local var
+ [0-9a-f]+:	8b 93 f0 ff ff ff[ 	]+mov    0xfffffff0\(%ebx\),%edx
+#				->R_386_TLS_TPOFF	[0x50000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 12[ 	]+mov    %gs:\(%edx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden but not local var
+ [0-9a-f]+:	8b 8b f4 ff ff ff[ 	]+mov    0xfffffff4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	[0x70000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 11[ 	]+mov    %gs:\(%ecx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 5d fc[ 	]+mov    0xfffffffc\(%ebp\),%ebx
+ [0-9a-f]+:	c9[ 	]+leave *
+ [0-9a-f]+:	c3[ 	]+ret *
Index: ld/testsuite/ld-i386/tlsdesc.rd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsdesc.rd
diff -N ld/testsuite/ld-i386/tlsdesc.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsdesc.rd 15 Sep 2005 22:39:23 -0000
@@ -0,0 +1,155 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --32
+#ld: -shared -melf_i386
+#readelf: -Ssrl
+#target: i?86-*-*
+
+There are [0-9]+ section headers, starting at offset 0x.*:
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+  \[ 1\] \.hash +.*
+  \[ 2\] \.dynsym +.*
+  \[ 3\] \.dynstr +.*
+  \[ 4\] \.rel.dyn +.*
+  \[ 5\] \.rel.plt +.*
+  \[ 6\] \.text +.*
+  \[ 7\] \.tdata +PROGBITS +[0-9a-f]+ [0-9a-f]+ 000060 00 WAT  0   0  1
+  \[ 8\] \.tbss +NOBITS +[0-9aa-f]+ [0-9a-f]+ 000020 00 WAT  0   0  1
+  \[ 9\] \.dynamic +.*
+  \[10\] \.got +.*
+  \[11\] \.got.plt +.*
+  \[12\] \.shstrtab +.*
+  \[13\] \.symtab +.*
+  \[14\] \.strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x[0-9a-f]+
+There are [0-9]+ program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  LOAD.*
+  LOAD.*
+  DYNAMIC.*
+  TLS +0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x0+60 0x0+80 R +0x1
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +.hash .dynsym .dynstr .rel.dyn .rel.plt .text *
+   01 +.tdata .dynamic .got .got.plt *
+   02 +.dynamic *
+   03 +.tdata .tbss *
+
+Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 20 entries:
+ Offset +Info +Type +Sym.Value +Sym. Name
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+50e R_386_TLS_TPOFF   0+8   sg3
+[0-9a-f]+ +0+625 R_386_TLS_TPOFF32 0+c   sg4
+[0-9a-f]+ +0+60e R_386_TLS_TPOFF   0+c   sg4
+[0-9a-f]+ +0+70e R_386_TLS_TPOFF   0+10   sg5
+[0-9a-f]+ +0+b25 R_386_TLS_TPOFF32 0+4   sg2
+
+Relocation section '.rel.plt' at offset 0x[0-9a-f]+ contains 5 entries:
+ Offset     Info    Type            Sym.Value  Sym. Name
+[0-9a-f]+ +0+827 R_386_TLS_DESC * 0+   sg1
+[0-9a-f]+ +0+27 R_386_TLS_DESC *
+[0-9a-f]+ +0+27 R_386_TLS_DESC *
+[0-9a-f]+ +0+27 R_386_TLS_DESC *
+[0-9a-f]+ +0+27 R_386_TLS_DESC *
+
+Symbol table '.dynsym' contains 16 entries:
+ +Num: + Value  Size Type + Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +7 sg8
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +7 sg3
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +7 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +7 sg5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +6 fn1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +7 sg2
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +7 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +7 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 54 entries:
+ +Num: +Value  Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +[0-9]+: 0+20 +0 TLS +LOCAL  DEFAULT +7 sl1
+ +[0-9]+: 0+24 +0 TLS +LOCAL  DEFAULT +7 sl2
+ +[0-9]+: 0+28 +0 TLS +LOCAL  DEFAULT +7 sl3
+ +[0-9]+: 0+2c +0 TLS +LOCAL  DEFAULT +7 sl4
+ +[0-9]+: 0+30 +0 TLS +LOCAL  DEFAULT +7 sl5
+ +[0-9]+: 0+34 +0 TLS +LOCAL  DEFAULT +7 sl6
+ +[0-9]+: 0+38 +0 TLS +LOCAL  DEFAULT +7 sl7
+ +[0-9]+: 0+3c +0 TLS +LOCAL  DEFAULT +7 sl8
+ +[0-9]+: 0+60 +0 TLS +LOCAL  HIDDEN +8 sH1
+ +[0-9]+: 0+ +0 TLS +LOCAL  HIDDEN +7 _TLS_MODULE_BASE_
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _DYNAMIC
+ +[0-9]+: 0+48 +0 TLS +LOCAL  HIDDEN +7 sh3
+ +[0-9]+: 0+64 +0 TLS +LOCAL  HIDDEN +8 sH2
+ +[0-9]+: 0+78 +0 TLS +LOCAL  HIDDEN +8 sH7
+ +[0-9]+: 0+58 +0 TLS +LOCAL  HIDDEN +7 sh7
+ +[0-9]+: 0+5c +0 TLS +LOCAL  HIDDEN +7 sh8
+ +[0-9]+: 0+6c +0 TLS +LOCAL  HIDDEN +8 sH4
+ +[0-9]+: 0+4c +0 TLS +LOCAL  HIDDEN +7 sh4
+ +[0-9]+: 0+68 +0 TLS +LOCAL  HIDDEN +8 sH3
+ +[0-9]+: 0+50 +0 TLS +LOCAL  HIDDEN +7 sh5
+ +[0-9]+: 0+70 +0 TLS +LOCAL  HIDDEN +8 sH5
+ +[0-9]+: 0+74 +0 TLS +LOCAL  HIDDEN +8 sH6
+ +[0-9]+: 0+7c +0 TLS +LOCAL  HIDDEN +8 sH8
+ +[0-9]+: 0+40 +0 TLS +LOCAL  HIDDEN +7 sh1
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+44 +0 TLS +LOCAL  HIDDEN +7 sh2
+ +[0-9]+: 0+54 +0 TLS +LOCAL  HIDDEN +7 sh6
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +7 sg8
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +7 sg3
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +7 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +7 sg5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +6 fn1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +7 sg2
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +7 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +7 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
Index: ld/testsuite/ld-i386/tlsdesc.s
===================================================================
RCS file: ld/testsuite/ld-i386/tlsdesc.s
diff -N ld/testsuite/ld-i386/tlsdesc.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsdesc.s 15 Sep 2005 22:39:24 -0000
@@ -0,0 +1,276 @@
+	.section ".tdata", "awT", @progbits
+	.globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8
+	.globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+	.hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	.text
+	.globl	fn1
+	.type	fn1,@function
+fn1:
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	pushl	%eax
+	call	1f
+1:	popl	%ebx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sg1@tlsdesc(%ebx), %eax
+	call	*sg1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is referenced through @gottpoff too */
+	leal	sg2@tlsdesc(%ebx), %eax
+	call	*sg2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is referenced through @gotntpoff too */
+	leal	sg3@tlsdesc(%ebx), %eax
+	call	*sg3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is referenced through @gottpoff and
+	   @gotntpoff too */
+	leal	sg4@tlsdesc(%ebx), %eax
+	call	*sg4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD against local variable */
+	leal	sl1@tlsdesc(%ebx), %eax
+	call	*sl1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against local variable referenced through @gottpoff too */
+	leal	sl2@tlsdesc(%ebx), %eax
+	call	*sl2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against local variable referenced through @gotntpoff
+	   too */
+	leal	sl3@tlsdesc(%ebx), %eax
+	call	*sl3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against local variable referenced through @gottpoff and
+	   @gotntpoff too */
+	leal	sl4@tlsdesc(%ebx), %eax
+	call	*sl4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD against hidden and local variable */
+	leal	sh1@tlsdesc(%ebx), %eax
+	call	*sh1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden and local variable referenced through
+	   @gottpoff too */
+	leal	sh2@tlsdesc(%ebx), %eax
+	call	*sh2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden and local variable referenced through
+	   @gotntpoff too */
+	leal	sh3@tlsdesc(%ebx), %eax
+	call	*sh3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden and local variable referenced through
+	   @gottpoff and @gotntpoff too */
+	leal	sh4@tlsdesc(%ebx), %eax
+	call	*sh4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD against hidden but not local variable */
+	leal	sH1@tlsdesc(%ebx), %eax
+	call	*sH1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   @gottpoff too */
+	leal	sH2@tlsdesc(%ebx), %eax
+	call	*sH2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   @gotntpoff too */
+	leal	sH3@tlsdesc(%ebx), %eax
+	call	*sH3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   @gottpoff and @gotntpoff too */
+	leal	sH4@tlsdesc(%ebx), %eax
+	call	*sH4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* LD */
+	leal	_TLS_MODULE_BASE_@tlsdesc(%ebx), %eax
+	call	*_TLS_MODULE_BASE_@tlscall(%eax)
+	nop;nop
+	leal	sl1@dtpoff(%eax), %edx
+	nop;nop
+	leal	2+sl2@dtpoff(%eax), %ecx
+	nop;nop;nop;nop
+
+	/* LD against hidden and local variables */
+	leal	sh1@dtpoff(%eax), %edx
+	nop;nop
+	leal	sh2@dtpoff+3(%eax), %ecx
+	nop;nop;nop;nop
+
+	/* LD against hidden but not local variables */
+	leal	sH1@dtpoff(%eax), %edx
+	nop;nop
+	leal	sH2@dtpoff+1(%eax), %ecx
+	nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sg2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sg4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sg3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sg4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sl2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sl4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sl3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sl4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against hidden and local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sh2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against hidden and local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sh4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden and local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sh3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden and local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sh4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against hidden but not local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sH2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against hidden but not local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sH4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden but not local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sH3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden but not local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sH4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* Direct access through %gs  */
+
+	/* @gotntpoff IE against global var  */
+	movl	sg5@gotntpoff(%ebx), %ecx
+	nop;nop
+	movl	%gs:(%ecx), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against local var  */
+	movl	sl5@gotntpoff(%ebx), %eax
+	nop;nop
+	movl	%gs:(%eax), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden and local var  */
+	movl	sh5@gotntpoff(%ebx), %edx
+	nop;nop
+	movl	%gs:(%edx), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden but not local var  */
+	movl	sH5@gotntpoff(%ebx), %ecx
+	nop;nop
+	movl	%gs:(%ecx), %edx
+	nop;nop;nop;nop
+
+	movl    -4(%ebp), %ebx
+	leave
+	ret
Index: ld/testsuite/ld-i386/tlsdesc.sd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsdesc.sd
diff -N ld/testsuite/ld-i386/tlsdesc.sd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsdesc.sd 15 Sep 2005 22:39:24 -0000
@@ -0,0 +1,20 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --32
+#ld: -shared -melf_i386
+#objdump: -s -j.got -j.got.plt
+#target: i?86-*-*
+
+.*:     file format elf32-i386
+
+Contents of section \.got:
+ [0-9a-f]+ dcffffff 28000000 d4ffffff 2c000000  .*
+ [0-9a-f]+ 30000000 00000000 48000000 9cffffff  .*
+ [0-9a-f]+ 00000000 00000000 00000000 94ffffff  .*
+ [0-9a-f]+ 6c000000 b4ffffff 4c000000 68000000  .*
+ [0-9a-f]+ 50000000 70000000 00000000 bcffffff  .*
+Contents of section \.got\.plt:
+ [0-9a-f]+ ec150000 00000000 00000000 00000000  .*
+ [0-9a-f]+ 20000000 00000000 60000000 00000000  .*
+ [0-9a-f]+ 00000000 00000000 00000000 00000000  .*
+ [0-9a-f]+ 40000000 +.*
Index: ld/testsuite/ld-i386/tlsdesc.td
===================================================================
RCS file: ld/testsuite/ld-i386/tlsdesc.td
diff -N ld/testsuite/ld-i386/tlsdesc.td
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsdesc.td 15 Sep 2005 22:39:24 -0000
@@ -0,0 +1,16 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --32
+#ld: -shared -melf_i386
+#objdump: -sj.tdata
+#target: i?86-*-*
+
+.*:     file format elf32-i386
+
+Contents of section \.tdata:
+ [0-9a-f]+ 11000000 12000000 13000000 14000000  .*
+ [0-9a-f]+ 15000000 16000000 17000000 18000000  .*
+ [0-9a-f]+ 41000000 42000000 43000000 44000000  .*
+ [0-9a-f]+ 45000000 46000000 47000000 48000000  .*
+ [0-9a-f]+ 01010000 02010000 03010000 04010000  .*
+ [0-9a-f]+ 05010000 06010000 07010000 08010000  .*
Index: ld/testsuite/ld-i386/tlsgdesc.dd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsgdesc.dd
diff -N ld/testsuite/ld-i386/tlsgdesc.dd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsgdesc.dd 15 Sep 2005 22:39:24 -0000
@@ -0,0 +1,156 @@
+#source: tlsgdesc.s
+#as: --32
+#ld: -shared -melf_i386
+#objdump: -drj.text
+#target: i?86-*-*
+
+.*: +file format elf32-i386
+
+Disassembly of section .text:
+
+[0-9a-f]+ <fc1>:
+ [0-9a-f]+:	55[ 	]+push   %ebp
+ [0-9a-f]+:	89 e5[ 	]+mov    %esp,%ebp
+ [0-9a-f]+:	53[ 	]+push   %ebx
+ [0-9a-f]+:	50[ 	]+push   %eax
+ [0-9a-f]+:	e8 00 00 00 00[ 	]+call   [0-9a-f]+ <.*>
+ [0-9a-f]+:	5b[ 	]+pop    %ebx
+ [0-9a-f]+:	81 c3 be 11 00 00[ 	]+add    \$0x[0-9a-f]+,%ebx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b e0 ff ff ff[ 	]+sub    0xffffffe0\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	sG3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b f0 ff ff ff[ 	]+add    0xfffffff0\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sG4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD
+ [0-9a-f]+:	8d 04 1d f8 ff ff ff[ 	]+lea    0xfffffff8\(,%ebx,1\),%eax
+#				->R_386_TLS_DTPMOD32	sG1
+ [0-9a-f]+:	e8 a9 ff ff ff[ 	]+call   [0-9a-f]+ <___tls_get_addr@plt>
+#				->R_386_JUMP_SLOT	___tls_get_addr
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 83 18 00 00 00[ 	]+lea    0x18\(%ebx\),%eax
+#				->R_386_TLS_DESC	sG1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 83 10 00 00 00[ 	]+lea    0x10\(%ebx\),%eax
+#				->R_386_TLS_DESC	sG2
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 04 1d e8 ff ff ff[ 	]+lea    0xffffffe8\(,%ebx,1\),%eax
+#				->R_386_TLS_DTPMOD32	sG2
+ [0-9a-f]+:	e8 81 ff ff ff[ 	]+call   [0-9a-f]+ <___tls_get_addr@plt>
+#				->R_386_JUMP_SLOT	___tls_get_addr
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gottpoff too
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	2b 83 e0 ff ff ff[ 	]+sub    0xffffffe0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 83 e0 ff ff ff[ 	]+mov    0xffffffe0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG3
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gotntpoff too
+ [0-9a-f]+:	8b 83 f0 ff ff ff[ 	]+mov    0xfffffff0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG4
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	03 83 f0 ff ff ff[ 	]+add    0xfffffff0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gotntpoff too
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	03 83 e4 ff ff ff[ 	]+add    0xffffffe4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 83 e4 ff ff ff[ 	]+mov    0xffffffe4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG5
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 f4 ff ff ff[ 	]+mov    0xfffffff4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG6
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	2b 83 f4 ff ff ff[ 	]+sub    0xfffffff4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b e4 ff ff ff[ 	]+add    0xffffffe4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sG5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b f4 ff ff ff[ 	]+sub    0xfffffff4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	sG6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 5d fc[ 	]+mov    0xfffffffc\(%ebp\),%ebx
+ [0-9a-f]+:	c9[ 	]+leave *
+ [0-9a-f]+:	c3[ 	]+ret *
Index: ld/testsuite/ld-i386/tlsgdesc.rd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsgdesc.rd
diff -N ld/testsuite/ld-i386/tlsgdesc.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsgdesc.rd 15 Sep 2005 22:39:24 -0000
@@ -0,0 +1,107 @@
+#source: tlsgdesc.s
+#as: --32
+#ld: -shared -melf_i386
+#readelf: -Ssrl
+#target: i?86-*-*
+
+There are [0-9]+ section headers, starting at offset 0x.*:
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+  \[ 1\] \.hash +.*
+  \[ 2\] \.dynsym +.*
+  \[ 3\] \.dynstr +.*
+  \[ 4\] \.rel.dyn +.*
+  \[ 5\] \.rel.plt +.*
+  \[ 6\] \.plt +.*
+  \[ 7\] \.text +.*
+  \[ 8\] \.dynamic +.*
+  \[ 9\] \.got +.*
+  \[10\] \.got.plt +.*
+  \[11\] \.shstrtab +.*
+  \[12\] \.symtab +.*
+  \[13\] \.strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x[0-9a-f]+
+There are [0-9]+ program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  LOAD.*
+  LOAD.*
+  DYNAMIC.*
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +.hash .dynsym .dynstr .rel.dyn .rel.plt .plt .text *
+   01 +.dynamic .got .got.plt *
+   02 +.dynamic *
+
+Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 8 entries:
+ Offset +Info +Type +Sym.Value +Sym. Name
+[0-9a-f]+ +0+225 R_386_TLS_TPOFF32 0+   sG3
+[0-9a-f]+ +0+30e R_386_TLS_TPOFF   0+   sG5
+[0-9a-f]+ +0+423 R_386_TLS_DTPMOD3 0+   sG2
+[0-9a-f]+ +0+424 R_386_TLS_DTPOFF3 0+   sG2
+[0-9a-f]+ +0+50e R_386_TLS_TPOFF   0+   sG4
+[0-9a-f]+ +0+725 R_386_TLS_TPOFF32 0+   sG6
+[0-9a-f]+ +0+923 R_386_TLS_DTPMOD3 0+   sG1
+[0-9a-f]+ +0+924 R_386_TLS_DTPOFF3 0+   sG1
+
+Relocation section '.rel.plt' at offset 0x[0-9a-f]+ contains 3 entries:
+ Offset     Info    Type            Sym.Value  Sym. Name
+[0-9a-f]+  0+c07 R_386_JUMP_SLOT   0+   ___tls_get_addr
+[0-9a-f]+  0+927 R_386_TLS_DESC    0+   sG1
+[0-9a-f]+  0+427 R_386_TLS_DESC    0+   sG2
+
+Symbol table '.dynsym' contains 13 entries:
+ +Num: + Value  Size Type + Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND ___tls_get_addr
+
+Symbol table '.symtab' contains 27 entries:
+ +Num: +Value  Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _DYNAMIC
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND ___tls_get_addr
Index: ld/testsuite/ld-i386/tlsgdesc.s
===================================================================
RCS file: ld/testsuite/ld-i386/tlsgdesc.s
diff -N ld/testsuite/ld-i386/tlsgdesc.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsgdesc.s 15 Sep 2005 22:39:24 -0000
@@ -0,0 +1,100 @@
+	.text
+	.globl	fc1
+	.type	fc1,@function
+fc1:
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	pushl	%eax
+	call	1f
+1:	popl	%ebx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sG3@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sG4@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sG1@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sG1@tlsdesc(%ebx), %eax
+	call	*sG1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sG2@tlsdesc(%ebx), %eax
+	call	*sG2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sG2@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE tpoff */
+	leal	sG3@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE tpoff */
+	leal	sG3@tlsdesc(%ebx), %eax
+	call	*sG3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE ntpoff */
+	leal	sG4@tlsdesc(%ebx), %eax
+	call	*sG4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE ntpoff */
+	leal	sG4@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE ntpoff */
+	leal	sG5@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE ntpoff */
+	leal	sG5@tlsdesc(%ebx), %eax
+	call	*sG5@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE tpoff */
+	leal	sG6@tlsdesc(%ebx), %eax
+	call	*sG6@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE tpoff */
+	leal	sG6@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sG5@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sG6@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	movl    -4(%ebp), %ebx
+	leave
+	ret
Index: ld/testsuite/ld-x86-64/tlsbindesc.dd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsbindesc.dd
diff -N ld/testsuite/ld-x86-64/tlsbindesc.dd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.dd 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,301 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -drj.text
+#target: x86_64-*-*
+
+# PT_TLS layout is:
+# Offset from   Offset from     Name
+# TCB base      TCB end
+# 0x00          -0xa0           sg1..sg8
+# 0x20          -0x80           sl1..sl8
+# 0x40          -0x60           sh1..sh8
+# 0x60          -0x40           bg1..bg8
+# 0x80          -0x20           bl1..bl8
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .text:
+
+0+401000 <fn2>:
+  [0-9a-f]+:	55[ 	]+push   %rbp
+  [0-9a-f]+:	48 89 e5[ 	]+mov    %rsp,%rbp
+#  GD -> IE because variable is not defined in executable
+  [0-9a-f]+:	48 8b 05 65 03 10 00[ 	]+mov    1049445\(%rip\),%rax +# 501370 <.*>
+#				-> R_X86_64_TPOFF64	sG1
+  [0-9a-f]+:	48 90[ 	]+rex64 nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable where
+#  the variable is referenced through IE too
+  [0-9a-f]+:	48 8b 05 48 03 10 00[ 	]+mov    1049416\(%rip\),%rax +# 501360 <.*>
+#				-> R_X86_64_TPOFF64	sG2
+  [0-9a-f]+:	48 90[ 	]+rex64 nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with global variable defined in executable
+  [0-9a-f]+:	48 c7 c0 60 ff ff ff[ 	]+mov    \$0xf+60,%rax
+#							sg1
+  [0-9a-f]+:	48 90[ 	]+rex64 nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with local variable defined in executable
+  [0-9a-f]+:	48 c7 c0 80 ff ff ff[ 	]+mov    \$0xf+80,%rax
+#							sl1
+  [0-9a-f]+:	48 90[ 	]+rex64 nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with hidden variable defined in executable
+  [0-9a-f]+:	48 c7 c0 a0 ff ff ff[ 	]+mov    \$0xf+a0,%rax
+#							sh1
+  [0-9a-f]+:	48 90[ 	]+rex64 nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LD -> LE
+  [0-9a-f]+:	48 c7 c0 60 ff ff ff[ 	]+mov    \$0xf+60,%rax
+  [0-9a-f]+:	48 90[ 	]+rex64 nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 90 81 ff ff ff[ 	]+lea    0xf+81\(%rax\),%rdx
+#							sl1+1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4c 8d 88 86 ff ff ff[ 	]+lea    0xf+86\(%rax\),%r9
+#							sl2+2
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LD -> LE against hidden variables
+  [0-9a-f]+:	48 8d 90 a0 ff ff ff[ 	]+lea    0xf+a0\(%rax\),%rdx
+#							sh1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 88 a7 ff ff ff[ 	]+lea    0xf+a7\(%rax\),%rcx
+#							sh2+3
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE against global var
+  [0-9a-f]+:	64 4c 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%r9
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4c 03 0d d6 02 10 00[ 	]+add    1049302\(%rip\),%r9 +# 501360 <.*>
+#				-> R_X86_64_TPOFF64	sG2
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against global var defined in exec
+  [0-9a-f]+:	64 4c 8b 14 25 00 00[ 	]+mov    %fs:0x0,%r10
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4d 8d 92 60 ff ff ff[ 	]+lea    0xf+60\(%r10\),%r10
+#							sg1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against local var
+  [0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 80 80 ff ff ff[ 	]+lea    0xf+80\(%rax\),%rax
+#							sl1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against hidden var
+  [0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 89 a0 ff ff ff[ 	]+lea    0xf+a0\(%rcx\),%rcx
+#							sh1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  Direct access through %fs
+#  IE against global var
+  [0-9a-f]+:	48 8b 0d 81 02 10 00[ 	]+mov    1049217\(%rip\),%rcx +# 501358 <.*>
+#				-> R_X86_64_TPOFF64	sG5
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 11[ 	]+mov    %fs:\(%rcx\),%rdx
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE->LE against local var
+  [0-9a-f]+:	49 c7 c3 90 ff ff ff[ 	]+mov    \$0xf+90,%r11
+#							sl5
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 4d 8b 23[ 	]+mov    %fs:\(%r11\),%r12
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE->LE against hidden var
+  [0-9a-f]+:	48 c7 c2 b0 ff ff ff[ 	]+mov    \$0xf+b0,%rdx
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 12[ 	]+mov    %fs:\(%rdx\),%rdx
+#							sh5
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	c9[ 	]+leaveq *
+  [0-9a-f]+:	c3[ 	]+retq *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+
+[0-9a-f]+ <_start>:
+  [0-9a-f]+:	55[ 	]+push   %rbp
+  [0-9a-f]+:	48 89 e5[ 	]+mov    %rsp,%rbp
+#  IE against global var
+  [0-9a-f]+:	64 4c 8b 1c 25 00 00[ 	]+mov    %fs:0x0,%r11
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4c 03 1d 4a 02 10 00[ 	]+add    1049162\(%rip\),%r11 +# 501368 <.*>
+#				-> R_X86_64_TPOFF64	sG6
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against global var defined in exec
+  [0-9a-f]+:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 92 d4 ff ff ff[ 	]+lea    0xf+d4\(%rdx\),%rdx
+#							bg6
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against local var
+  [0-9a-f]+:	64 4c 8b 24 25 00 00[ 	]+mov    %fs:0x0,%r12
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	49 81 c4 f4 ff ff ff[ 	]+add    \$0xf+f4,%r12
+#							bl6
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  direct %fs access IE -> LE against local var
+  [0-9a-f]+:	48 c7 c2 fc ff ff ff[ 	]+mov    \$0xf+fc,%rdx
+#							bl8
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 02[ 	]+mov    %fs:\(%rdx\),%rax
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against hidden but not local var
+  [0-9a-f]+:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 92 b4 ff ff ff[ 	]+lea    0xf+b4\(%rdx\),%rdx
+#							sh6
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  direct %fs access IE -> LE against hidden but not local var
+  [0-9a-f]+:	48 c7 c2 bc ff ff ff[ 	]+mov    \$0xf+bc,%rdx
+#							sh8
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 02[ 	]+mov    %fs:\(%rdx\),%rax
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, global var defined in exec
+  [0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 90 64 ff ff ff[ 	]+lea    0xf+64\(%rax\),%rdx
+#							sg2
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, local var, non-canonical sequence
+  [0-9a-f]+:	49 c7 c1 e6 ff ff ff[ 	]+mov    \$0xf+e6,%r9
+#							bl2+2
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4c 01 ca[ 	]+add    %r9,%rdx
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, hidden var defined in exec, non-canonical sequence
+  [0-9a-f]+:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 81 c2 a5 ff ff ff[ 	]+add    \$0xf+a5,%rdx
+#							sh2+1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  Direct %fs access
+#  LE, global var defined in exec
+  [0-9a-f]+:	64 48 8b 04 25 68 ff[ 	]+mov    %fs:0xf+68,%rax
+  [0-9a-f]+:	ff ff *
+#							sg3
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, local var
+  [0-9a-f]+:	64 4c 8b 14 25 eb ff[ 	]+mov    %fs:0xf+eb,%r10
+  [0-9a-f]+:	ff ff *
+#							bl3+3
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, hidden var defined in exec
+  [0-9a-f]+:	64 48 8b 14 25 a9 ff[ 	]+mov    %fs:0xf+a9,%rdx
+  [0-9a-f]+:	ff ff *
+#							sh3+1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	c9[ 	]+leaveq *
+  [0-9a-f]+:	c3[ 	]+retq *
Index: ld/testsuite/ld-x86-64/tlsbindesc.rd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsbindesc.rd
diff -N ld/testsuite/ld-x86-64/tlsbindesc.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.rd 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,141 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --64
+#ld: -shared -melf_x86_64
+#readelf: -WSsrl
+#target: x86_64-*-*
+
+There are 15 section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+  \[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 00 +0 +0 +0
+  \[ 1\] .interp +.*
+  \[ 2\] .hash +.*
+  \[ 3\] .dynsym +.*
+  \[ 4\] .dynstr +.*
+  \[ 5\] .rela.dyn +.*
+  \[ 6\] .text +PROGBITS +0+401000 0+1000 0+1f6 00 +AX +0 +0 +4096
+  \[ 7\] .tdata +PROGBITS +0+5011f6 0+11f6 0+60 00 WAT +0 +0 +1
+  \[ 8\] .tbss +NOBITS +0+501256 0+1256 0+40 00 WAT +0 +0 +1
+  \[ 9\] .dynamic +DYNAMIC +0+501258 0+1258 0+100 10 +WA +4 +0 +8
+  \[10\] .got +PROGBITS +0+501358 0+1358 0+20 08 +WA +0 +0 +8
+  \[11\] .got.plt +PROGBITS +0+501378 0+1378 0+18 08 +WA +0 +0 +8
+  \[12\] .shstrtab +.*
+  \[13\] .symtab +.*
+  \[14\] .strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x401108
+There are 6 program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  PHDR.*
+  INTERP.*
+.*Requesting program interpreter.*
+  LOAD +0x0+ 0x0+400000 0x0+400000 0x0+11f6 0x0+11f6 R E 0x100000
+  LOAD +0x0+11f6 0x0+5011f6 0x0+5011f6 0x0+19a 0x0+19a RW  0x100000
+  DYNAMIC +0x0+1258 0x0+501258 0x0+501258 0x0+100 0x0+100 RW  0x8
+  TLS +0x0+11f6 0x0+5011f6 0x0+5011f6 0x0+60 0x0+a0 R +0x1
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 *
+   01 +.interp *
+   02 +.interp .hash .dynsym .dynstr .rela.dyn .text *
+   03 +.tdata .dynamic .got .got.plt *
+   04 +.dynamic *
+   05 +.tdata .tbss *
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 4 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+0+501358  0+100000012 R_X86_64_TPOFF64 +0+ sG5 \+ 0
+0+501360  0+200000012 R_X86_64_TPOFF64 +0+ sG2 \+ 0
+0+501368  0+400000012 R_X86_64_TPOFF64 +0+ sG6 \+ 0
+0+501370  0+500000012 R_X86_64_TPOFF64 +0+ sG1 \+ 0
+
+Symbol table '.dynsym' contains 8 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+[0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: 0+[0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: 0+[0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 67 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +[0-9]+: 0+20 +0 TLS +LOCAL  DEFAULT +7 sl1
+ +[0-9]+: 0+24 +0 TLS +LOCAL  DEFAULT +7 sl2
+ +[0-9]+: 0+28 +0 TLS +LOCAL  DEFAULT +7 sl3
+ +[0-9]+: 0+2c +0 TLS +LOCAL  DEFAULT +7 sl4
+ +[0-9]+: 0+30 +0 TLS +LOCAL  DEFAULT +7 sl5
+ +[0-9]+: 0+34 +0 TLS +LOCAL  DEFAULT +7 sl6
+ +[0-9]+: 0+38 +0 TLS +LOCAL  DEFAULT +7 sl7
+ +[0-9]+: 0+3c +0 TLS +LOCAL  DEFAULT +7 sl8
+ +[0-9]+: 0+80 +0 TLS +LOCAL  DEFAULT +8 bl1
+ +[0-9]+: 0+84 +0 TLS +LOCAL  DEFAULT +8 bl2
+ +[0-9]+: 0+88 +0 TLS +LOCAL  DEFAULT +8 bl3
+ +[0-9]+: 0+8c +0 TLS +LOCAL  DEFAULT +8 bl4
+ +[0-9]+: 0+90 +0 TLS +LOCAL  DEFAULT +8 bl5
+ +[0-9]+: 0+94 +0 TLS +LOCAL  DEFAULT +8 bl6
+ +[0-9]+: 0+98 +0 TLS +LOCAL  DEFAULT +8 bl7
+ +[0-9]+: 0+9c +0 TLS +LOCAL  DEFAULT +8 bl8
+ +[0-9]+: 0+0 +0 TLS +LOCAL  HIDDEN +7 _TLS_MODULE_BASE_
+ +[0-9]+: 0+501258 +0 OBJECT  LOCAL  HIDDEN    9 _DYNAMIC
+ +[0-9]+: 0+501378 +0 OBJECT  LOCAL  HIDDEN   11 _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +7 sg8
+ +[0-9]+: 0+7c +0 TLS +GLOBAL DEFAULT +8 bg8
+ +[0-9]+: 0+74 +0 TLS +GLOBAL DEFAULT +8 bg6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+68 +0 TLS +GLOBAL DEFAULT +8 bg3
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +7 sg3
+ +[0-9]+: 0+48 +0 TLS +GLOBAL HIDDEN +7 sh3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +7 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +7 sg5
+ +[0-9]+: 0+70 +0 TLS +GLOBAL DEFAULT +8 bg5
+ +[0-9]+: 0+58 +0 TLS +GLOBAL HIDDEN +7 sh7
+ +[0-9]+: 0+5c +0 TLS +GLOBAL HIDDEN +7 sh8
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1
+ +[0-9]+: 0+401108 +0 FUNC +GLOBAL DEFAULT +6 _start
+ +[0-9]+: 0+4c +0 TLS +GLOBAL HIDDEN +7 sh4
+ +[0-9]+: 0+78 +0 TLS +GLOBAL DEFAULT +8 bg7
+ +[0-9]+: 0+50 +0 TLS +GLOBAL HIDDEN +7 sh5
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: 0+401000 +0 FUNC +GLOBAL DEFAULT +6 fn2
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +7 sg2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: 0+40 +0 TLS +GLOBAL HIDDEN +7 sh1
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +7 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +7 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 0+44 +0 TLS +GLOBAL HIDDEN +7 sh2
+ +[0-9]+: 0+54 +0 TLS +GLOBAL HIDDEN +7 sh6
+ +[0-9]+: 0+64 +0 TLS +GLOBAL DEFAULT +8 bg2
+ +[0-9]+: 0+60 +0 TLS +GLOBAL DEFAULT +8 bg1
+ +[0-9]+: 0+6c +0 TLS +GLOBAL DEFAULT +8 bg4
Index: ld/testsuite/ld-x86-64/tlsbindesc.s
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsbindesc.s
diff -N ld/testsuite/ld-x86-64/tlsbindesc.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.s 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,128 @@
+	/* Force .data aligned to 4K, so that .got very likely gets at
+	   0x5021a0 (0x60 bytes .tdata and 0x140 bytes .dynamic)  */
+	.data
+	.balign	4096
+	.section ".tdata", "awT", @progbits
+	.globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8
+	.globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+	.hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	/* Force .text aligned to 4K, so it very likely gets at 0x401000.  */
+	.text
+	.balign	4096
+	.globl	fn2
+	.type	fn2,@function
+fn2:
+	pushq	%rbp
+	movq	%rsp, %rbp
+
+	/* GD -> IE because variable is not defined in executable */
+	leaq	sG1@tlsdesc(%rip), %rax
+	call	*sG1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through IE too */
+	leaq	sG2@tlsdesc(%rip), %rax
+	call	*sG2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with global variable defined in executable */
+	leaq	sg1@tlsdesc(%rip), %rax
+	call	*sg1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with local variable defined in executable */
+	leaq	sl1@tlsdesc(%rip), %rax
+	call	*sl1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with hidden variable defined in executable */
+	leaq	sh1@tlsdesc(%rip), %rax
+	call	*sh1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* LD -> LE */
+	leaq	_TLS_MODULE_BASE_@tlsdesc(%rip), %rax
+	call	*_TLS_MODULE_BASE_@tlscall(%rax)
+	nop;nop
+	leaq	1+sl1@dtpoff(%rax), %rdx
+	nop;nop
+	leaq	sl2@dtpoff+2(%rax), %r9
+	nop;nop;nop;nop
+
+	/* LD -> LE against hidden variables */
+	leaq	sh1@dtpoff(%rax), %rdx
+	nop;nop
+	leaq	3+sh2@dtpoff(%rax), %rcx
+	nop;nop;nop;nop
+
+	/* IE against global var  */
+	movq	%fs:0, %r9
+	nop;nop
+	addq	sG2@gottpoff(%rip), %r9
+	nop;nop;nop;nop
+
+	/* IE -> LE against global var defined in exec */
+	movq	%fs:0, %r10
+	nop;nop
+	addq	sg1@gottpoff(%rip), %r10
+	nop;nop;nop;nop
+
+	/* IE -> LE against local var */
+	movq	%fs:0, %rax
+	nop;nop
+	addq	sl1@gottpoff(%rip), %rax
+	nop;nop;nop;nop
+
+	/* IE -> LE against hidden var */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sh1@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* Direct access through %fs  */
+
+	/* IE against global var  */
+	movq	sG5@gottpoff(%rip), %rcx
+	nop;nop
+	movq	%fs:(%rcx), %rdx
+	nop;nop;nop;nop
+
+	/* IE->LE against local var  */
+	movq	sl5@gottpoff(%rip), %r11
+	nop;nop
+	movq	%fs:(%r11), %r12
+	nop;nop;nop;nop
+
+	/* IE->LE against hidden var  */
+	movq	sh5@gottpoff(%rip), %rdx
+	nop;nop
+	movq	%fs:(%rdx), %rdx
+	nop;nop;nop;nop
+
+	leave
+	ret
Index: ld/testsuite/ld-x86-64/tlsbindesc.sd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsbindesc.sd
diff -N ld/testsuite/ld-x86-64/tlsbindesc.sd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.sd 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,12 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -sj.got
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Contents of section .got:
+ 501358 00000000 00000000 00000000 00000000  .*
+ 501368 00000000 00000000 00000000 00000000  .*
Index: ld/testsuite/ld-x86-64/tlsbindesc.td
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsbindesc.td
diff -N ld/testsuite/ld-x86-64/tlsbindesc.td
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.td 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,16 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -sj.tdata
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Contents of section .tdata:
+ 5011f6 11000000 12000000 13000000 14000000  .*
+ 501206 15000000 16000000 17000000 18000000  .*
+ 501216 41000000 42000000 43000000 44000000  .*
+ 501226 45000000 46000000 47000000 48000000  .*
+ 501236 01010000 02010000 03010000 04010000  .*
+ 501246 05010000 06010000 07010000 08010000  .*
Index: ld/testsuite/ld-x86-64/tlsdesc.dd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsdesc.dd
diff -N ld/testsuite/ld-x86-64/tlsdesc.dd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsdesc.dd 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,200 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -drj.text
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .text:
+
+0+[0-9a-f]+ <fn1>:
+ +[0-9a-f]+:	55[ 	]+push   %rbp
+ +[0-9a-f]+:	48 89 e5[ 	]+mov    %rsp,%rbp
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD
+ +[0-9a-f]+:	48 8d 05 89 03 10 00[ 	]+lea    1049481\(%rip\),%rax +# 101398 <.*>
+#				-> R_X86_64_TLSDESC	sg1
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through IE too
+ +[0-9a-f]+:	48 8b 05 1c 03 10 00[ 	]+mov    1049372\(%rip\),%rax +# 101338 <.*>
+#				-> R_X86_64_TPOFF64	sg2
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD against local variable
+ +[0-9a-f]+:	48 8d 05 3f 03 10 00[ 	]+lea    1049407\(%rip\),%rax +# 101368 <.*>
+#				-> R_X86_64_TLSDESC	[0 0x2000000000000000]
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against local variable referenced through IE too
+ +[0-9a-f]+:	48 8b 05 d2 02 10 00[ 	]+mov    1049298\(%rip\),%rax +# 101308 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x24
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD against hidden and local variable
+ +[0-9a-f]+:	48 8d 05 65 03 10 00[ 	]+lea    1049445\(%rip\),%rax +# 1013a8 <.*>
+#				-> R_X86_64_TLSDESC	[0 0x4000000000000000]
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden and local variable referenced through IE too
+ +[0-9a-f]+:	48 8b 05 f0 02 10 00[ 	]+mov    1049328\(%rip\),%rax +# 101340 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x44
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD against hidden but not local variable
+ +[0-9a-f]+:	48 8d 05 1b 03 10 00[ 	]+lea    1049371\(%rip\),%rax +# 101378 <.*>
+#				-> R_X86_64_TLSDESC	[0 0x6000000000000000]
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden but not local variable referenced through IE too
+ +[0-9a-f]+:	48 8b 05 ae 02 10 00[ 	]+mov    1049262\(%rip\),%rax +# 101318 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x64
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  LD
+ +[0-9a-f]+:	48 8d 05 11 03 10 00[ 	]+lea    1049361\(%rip\),%rax +# 101388 <.*>
+#				-> R_X86_64_TLSDESC	[0 0x000000000000000]
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8d 90 20 00 00 00[ 	]+lea    0x20\(%rax\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	4c 8d 88 26 00 00 00[ 	]+lea    0x26\(%rax\),%r9
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  LD against hidden and local variables
+ +[0-9a-f]+:	48 8d 90 40 00 00 00[ 	]+lea    0x40\(%rax\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8d 88 47 00 00 00[ 	]+lea    0x47\(%rax\),%rcx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  LD against hidden but not local variables
+ +[0-9a-f]+:	4c 8d a0 60 00 00 00[ 	]+lea    0x60\(%rax\),%r12
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8d 88 65 00 00 00[ 	]+lea    0x65\(%rax\),%rcx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against global var
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 71 02 10 00[ 	]+add    1049201\(%rip\),%rcx +# 101338 <.*>
+#				-> R_X86_64_TPOFF64	sg2
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against local var
+ +[0-9a-f]+:	64 4c 8b 34 25 00 00[ 	]+mov    %fs:0x0,%r14
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	4c 03 35 2b 02 10 00[ 	]+add    1049131\(%rip\),%r14 +# 101308 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x24
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against hidden and local var
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 4d 02 10 00[ 	]+add    1049165\(%rip\),%rcx +# 101340 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x44
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against hidden but not local var
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 0f 02 10 00[ 	]+add    1049103\(%rip\),%rcx +# 101318 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x64
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  Direct access through %fs
+#  IE against global var
+ +[0-9a-f]+:	48 8b 0d 0c 02 10 00[ 	]+mov    1049100\(%rip\),%rcx +# 101320 <.*>
+#				-> R_X86_64_TPOFF64	sg5
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 11[ 	]+mov    %fs:\(%rcx\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against local var
+ +[0-9a-f]+:	4c 8b 15 eb 01 10 00[ 	]+mov    1049067\(%rip\),%r10 +# 101310 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x30
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 4d 8b 22[ 	]+mov    %fs:\(%r10\),%r12
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against hidden and local var
+ +[0-9a-f]+:	48 8b 15 f2 01 10 00[ 	]+mov    1049074\(%rip\),%rdx +# 101328 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x50
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 12[ 	]+mov    %fs:\(%rdx\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against hidden but not local var
+ +[0-9a-f]+:	48 8b 0d e9 01 10 00[ 	]+mov    1049065\(%rip\),%rcx +# 101330 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x70
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 11[ 	]+mov    %fs:\(%rcx\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	c9[ 	]+leaveq *
+ +[0-9a-f]+:	c3[ 	]+retq *
+ +[0-9a-f]+:	90[ 	]+nop *
Index: ld/testsuite/ld-x86-64/tlsdesc.pd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsdesc.pd
diff -N ld/testsuite/ld-x86-64/tlsdesc.pd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsdesc.pd 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,26 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -drj.plt
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .plt:
+
+0000000000000470 <.*@plt-0x10>:
+ 470:	ff 35 e2 0e 10 00    	pushq  1052386\(%rip\)        # 101358 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ 476:	ff 25 e4 0e 10 00    	jmpq   \*1052388\(%rip\)        # 101360 <_GLOBAL_OFFSET_TABLE_\+0x10>
+ 47c:	90                   	nop    
+ 47d:	90                   	nop    
+ 47e:	90                   	nop    
+ 47f:	90                   	nop    
+0000000000000480 <.*@plt>:
+ 480:	ff 35 d2 0e 10 00    	pushq  1052370\(%rip\)        # 101358 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ 486:	ff 25 bc 0e 10 00    	jmpq   \*1052348\(%rip\)        # 101348 <_DYNAMIC\+0x190>
+ 48c:	90                   	nop    
+ 48d:	90                   	nop    
+ 48e:	90                   	nop    
+ 48f:	90                   	nop    
+
Index: ld/testsuite/ld-x86-64/tlsdesc.rd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsdesc.rd
diff -N ld/testsuite/ld-x86-64/tlsdesc.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsdesc.rd 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,164 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#readelf: -WSsrld
+#target: x86_64-*-*
+
+There are 16 section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+  \[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 00 +0 +0 +0
+  \[ 1\] .hash +.*
+  \[ 2\] .dynsym +.*
+  \[ 3\] .dynstr +.*
+  \[ 4\] .rela.dyn +.*
+  \[ 5\] .rela.plt +.*
+  \[ 6\] .plt +PROGBITS +0+470 0+470 0+20 10 +AX +0 +0 +4
+  \[ 7\] .text +PROGBITS +0+1000 0+1000 0+154 00 +AX +0 +0 4096
+  \[ 8\] .tdata +PROGBITS +0+101154 0+1154 0+60 00 WAT +0 +0 +1
+  \[ 9\] .tbss +NOBITS +0+1011b4 0+11b4 0+20 00 WAT +0 +0 +1
+  \[10\] .dynamic +DYNAMIC +0+1011b8 0+11b8 0+150 10 +WA +3 +0 +8
+  \[11\] .got +PROGBITS +0+101308 0+1308 0+48 08 +WA +0 +0 +8
+  \[12\] .got.plt +PROGBITS +0+101350 0+1350 0+68 08 +WA +0 +0 +8
+  \[13\] .shstrtab +.*
+  \[14\] .symtab +.*
+  \[15\] .strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x1000
+There are 4 program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  LOAD +0x0+ 0x0+ 0x0+ 0x[0-9a-f]+ 0x[0-9a-f]+ R E 0x100000
+  LOAD +0x0+1154 0x0+101154 0x0+101154 0x0+264 0x0+264 RW +0x100000
+  DYNAMIC +0x0+11b8 0x0+1011b8 0x0+1011b8 0x0+150 0x0+150 RW +0x8
+  TLS +0x0+1154 0x0+101154 0x0+101154 0x0+60 0x0+80 R +0x1
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +.hash .dynsym .dynstr .rela.dyn .rela.plt .plt .text *
+   01 +.tdata .dynamic .got .got.plt *
+   02 +.dynamic *
+   03 +.tdata .tbss *
+
+Dynamic section at offset 0x[0-9a-f]+ contains 16 entries:
+ +Tag +Type +Name/Value
+ 0x[0-9a-f]+ +\(HASH\).*
+ 0x[0-9a-f]+ +\(STRTAB\).*
+ 0x[0-9a-f]+ +\(SYMTAB\).*
+ 0x[0-9a-f]+ +\(STRSZ\).*
+ 0x[0-9a-f]+ +\(SYMENT\).*
+ 0x[0-9a-f]+ +\(PLTGOT\).*
+ 0x[0-9a-f]+ +\(PLTRELSZ\).*
+ 0x[0-9a-f]+ +\(PLTREL\).*
+ 0x[0-9a-f]+ +\(JMPREL\).*
+ 0x[0-9a-f]+ +\(TLSDESC_PLT\) +0x480
+ 0x[0-9a-f]+ +\(TLSDESC_GOT\) +0x101348
+ 0x[0-9a-f]+ +\(RELA\).*
+ 0x[0-9a-f]+ +\(RELASZ\).*
+ 0x[0-9a-f]+ +\(RELAENT\).*
+ 0x[0-9a-f]+ +\(FLAGS\).*
+ 0x[0-9a-f]+ +\(NULL\).*
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 8 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+0+101308  0+12 R_X86_64_TPOFF64 +0+24
+0+101310  0+12 R_X86_64_TPOFF64 +0+30
+0+101318  0+12 R_X86_64_TPOFF64 +0+64
+0+101328  0+12 R_X86_64_TPOFF64 +0+50
+0+101330  0+12 R_X86_64_TPOFF64 +0+70
+0+101340  0+12 R_X86_64_TPOFF64 +0+44
+0+101320  0+700000012 R_X86_64_TPOFF64 +0+10 sg5 \+ 0
+0+101338  0+b00000012 R_X86_64_TPOFF64 +0+4 sg2 \+ 0
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 5 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+0+101398  0+80000001c R_X86_64_TLSDESC +0+ sg1 \+ 0
+0+101368  0+1c R_X86_64_TLSDESC +0+20
+0+1013a8  0+1c R_X86_64_TLSDESC +0+40
+0+101378  0+1c R_X86_64_TLSDESC +0+60
+0+101388  0+1c R_X86_64_TLSDESC +0+
+
+Symbol table '.dynsym' contains 16 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +8 sg8
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +8 sg3
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +8 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +8 sg5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +8 sg1
+ +[0-9]+: 0+1000 +0 FUNC +GLOBAL DEFAULT +7 fn1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +8 sg2
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +8 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +8 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 55 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +15 *
+ +[0-9]+: 0+20 +0 TLS +LOCAL  DEFAULT +8 sl1
+ +[0-9]+: 0+24 +0 TLS +LOCAL  DEFAULT +8 sl2
+ +[0-9]+: 0+28 +0 TLS +LOCAL  DEFAULT +8 sl3
+ +[0-9]+: 0+2c +0 TLS +LOCAL  DEFAULT +8 sl4
+ +[0-9]+: 0+30 +0 TLS +LOCAL  DEFAULT +8 sl5
+ +[0-9]+: 0+34 +0 TLS +LOCAL  DEFAULT +8 sl6
+ +[0-9]+: 0+38 +0 TLS +LOCAL  DEFAULT +8 sl7
+ +[0-9]+: 0+3c +0 TLS +LOCAL  DEFAULT +8 sl8
+ +[0-9]+: 0+60 +0 TLS +LOCAL  HIDDEN +9 sH1
+ +[0-9]+: 0+ +0 TLS +LOCAL  HIDDEN +8 _TLS_MODULE_BASE_
+ +[0-9]+: 0+1011b8 +0 OBJECT  LOCAL  HIDDEN  ABS _DYNAMIC
+ +[0-9]+: 0+48 +0 TLS +LOCAL  HIDDEN +8 sh3
+ +[0-9]+: 0+64 +0 TLS +LOCAL  HIDDEN +9 sH2
+ +[0-9]+: 0+78 +0 TLS +LOCAL  HIDDEN +9 sH7
+ +[0-9]+: 0+58 +0 TLS +LOCAL  HIDDEN +8 sh7
+ +[0-9]+: 0+5c +0 TLS +LOCAL  HIDDEN +8 sh8
+ +[0-9]+: 0+6c +0 TLS +LOCAL  HIDDEN +9 sH4
+ +[0-9]+: 0+4c +0 TLS +LOCAL  HIDDEN +8 sh4
+ +[0-9]+: 0+68 +0 TLS +LOCAL  HIDDEN +9 sH3
+ +[0-9]+: 0+50 +0 TLS +LOCAL  HIDDEN +8 sh5
+ +[0-9]+: 0+70 +0 TLS +LOCAL  HIDDEN +9 sH5
+ +[0-9]+: 0+74 +0 TLS +LOCAL  HIDDEN +9 sH6
+ +[0-9]+: 0+7c +0 TLS +LOCAL  HIDDEN +9 sH8
+ +[0-9]+: 0+40 +0 TLS +LOCAL  HIDDEN +8 sh1
+ +[0-9]+: 0+101350 +0 OBJECT  LOCAL  HIDDEN  ABS _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+44 +0 TLS +LOCAL  HIDDEN +8 sh2
+ +[0-9]+: 0+54 +0 TLS +LOCAL  HIDDEN +8 sh6
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +8 sg8
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +8 sg3
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +8 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +8 sg5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +8 sg1
+ +[0-9]+: 0+1000 +0 FUNC +GLOBAL DEFAULT +7 fn1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +8 sg2
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +8 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +8 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
Index: ld/testsuite/ld-x86-64/tlsdesc.s
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsdesc.s
diff -N ld/testsuite/ld-x86-64/tlsdesc.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsdesc.s 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,157 @@
+	/* Force .data aligned to 4K, so .got very likely gets at 0x102190
+	   (0x60 bytes .tdata and 0x130 bytes .dynamic)  */
+        .data
+        .balign 4096
+	.section ".tdata", "awT", @progbits
+	.globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8
+	.globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+	.hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	/* Force .text aligned to 4K, so it very likely gets at 0x1000.  */
+	.text
+	.balign	4096
+	.globl	fn1
+	.type	fn1,@function
+fn1:
+	pushq	%rbp
+	movq	%rsp, %rbp
+	nop;nop;nop;nop
+
+	/* GD */
+	leaq	sg1@tlsdesc(%rip), %rax
+	call	*sg1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is referenced through IE too */
+	leaq	sg2@tlsdesc(%rip), %rax
+	call	*sg2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD against local variable */
+	leaq	sl1@tlsdesc(%rip), %rax
+	call	*sl1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against local variable referenced through IE too */
+	leaq	sl2@tlsdesc(%rip), %rax
+	call	*sl2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD against hidden and local variable */
+	leaq	sh1@tlsdesc(%rip), %rax
+	call	*sh1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden and local variable referenced through
+	   IE too */
+	leaq	sh2@tlsdesc(%rip), %rax
+	call	*sh2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD against hidden but not local variable */
+	leaq	sH1@tlsdesc(%rip), %rax
+	call	*sH1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   IE too */
+	leaq	sH2@tlsdesc(%rip), %rax
+	call	*sH2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* LD */
+	leaq	_TLS_MODULE_BASE_@tlsdesc(%rip), %rax
+	call	*_TLS_MODULE_BASE_@tlscall(%rax)
+	nop;nop
+	leaq	sl1@dtpoff(%rax), %rdx
+	nop;nop
+	leaq	2+sl2@dtpoff(%rax), %r9
+	nop;nop;nop;nop
+
+	/* LD against hidden and local variables */
+	leaq	sh1@dtpoff(%rax), %rdx
+	nop;nop
+	leaq	sh2@dtpoff+3(%rax), %rcx
+	nop;nop;nop;nop
+
+	/* LD against hidden but not local variables */
+	leaq	sH1@dtpoff(%rax), %r12
+	nop;nop
+	leaq	sH2@dtpoff+1(%rax), %rcx
+	nop;nop
+
+	/* IE against global var  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sg2@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* IE against local var  */
+	movq	%fs:0, %r14
+	nop;nop
+	addq	sl2@gottpoff(%rip), %r14
+	nop;nop;nop;nop
+
+	/* IE against hidden and local var  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sh2@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* IE against hidden but not local var  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sH2@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* Direct access through %fs  */
+
+	/* IE against global var  */
+	movq	sg5@gottpoff(%rip), %rcx
+	nop;nop
+	movq	%fs:(%rcx), %rdx
+	nop;nop;nop;nop
+
+	/* IE against local var  */
+	movq	sl5@gottpoff(%rip), %r10
+	nop;nop
+	movq	%fs:(%r10), %r12
+	nop;nop;nop;nop
+
+	/* IE against hidden and local var  */
+	movq	sh5@gottpoff(%rip), %rdx
+	nop;nop
+	movq	%fs:(%rdx), %rdx
+	nop;nop;nop;nop
+
+	/* IE against hidden but not local var  */
+	movq	sH5@gottpoff(%rip), %rcx
+	nop;nop
+	movq	%fs:(%rcx), %rdx
+	nop;nop;nop;nop
+
+	leave
+	ret
Index: ld/testsuite/ld-x86-64/tlsdesc.sd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsdesc.sd
diff -N ld/testsuite/ld-x86-64/tlsdesc.sd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsdesc.sd 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,23 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -s -j.got -j.got.plt
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Contents of section \.got:
+ 101308 00000000 00000000 00000000 00000000  .*
+ 101318 00000000 00000000 00000000 00000000  .*
+ 101328 00000000 00000000 00000000 00000000  .*
+ 101338 00000000 00000000 00000000 00000000  .*
+ 101348 00000000 00000000                    .*
+Contents of section \.got\.plt:
+ 101350 b8111000 00000000 00000000 00000000  .*
+ 101360 00000000 00000000 00000000 00000000  .*
+ 101370 00000000 00000000 00000000 00000000  .*
+ 101380 00000000 00000000 00000000 00000000  .*
+ 101390 00000000 00000000 00000000 00000000  .*
+ 1013a0 00000000 00000000 00000000 00000000  .*
+ 1013b0 00000000 00000000                    .*
Index: ld/testsuite/ld-x86-64/tlsdesc.td
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsdesc.td
diff -N ld/testsuite/ld-x86-64/tlsdesc.td
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsdesc.td 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,16 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -sj.tdata
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Contents of section .tdata:
+ 101154 11000000 12000000 13000000 14000000  .*
+ 101164 15000000 16000000 17000000 18000000  .*
+ 101174 41000000 42000000 43000000 44000000  .*
+ 101184 45000000 46000000 47000000 48000000  .*
+ 101194 01010000 02010000 03010000 04010000  .*
+ 1011a4 05010000 06010000 07010000 08010000  .*
Index: ld/testsuite/ld-x86-64/tlsgdesc.dd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsgdesc.dd
diff -N ld/testsuite/ld-x86-64/tlsgdesc.dd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsgdesc.dd 15 Sep 2005 22:39:27 -0000
@@ -0,0 +1,165 @@
+#source: tlsgdesc.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -drj.text
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .text:
+
+0+[0-9a-f]+ <fc1>:
+ +[0-9a-f]+:	55[ 	]+push   %rbp
+ +[0-9a-f]+:	48 89 e5[ 	]+mov    %rsp,%rbp
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# IE
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 5e 02 10 00[ 	]+add    1049182\(%rip\),%rcx +# 100660 <.*>
+#				-> R_X86_64_TPOFF64	sG3
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# IE
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 68 02 10 00[ 	]+add    1049192\(%rip\),%rcx +# 100680 <.*>
+#				-> R_X86_64_TPOFF64	sG4
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD, gd first
+ +[0-9a-f]+:	66 48 8d 3d 6c 02 10[ 	]+lea    1049196\(%rip\),%rdi +# 100690 <.*>
+ +[0-9a-f]+:	00 *
+#				-> R_X86_64_DTPMOD64	sG1
+ +[0-9a-f]+:	66[ 	]+data16
+ +[0-9a-f]+:	66[ 	]+data16
+ +[0-9a-f]+:	48 e8 9c ff ff ff[ 	]+rex64 callq  [0-9a-f]+ <.*>
+#				-> R_X86_64_JUMP_SLOT	__tls_get_addr
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8d 05 a1 02 10 00[ 	]+lea    1049249\(%rip\),%rax +# 1006d8 <.*>
+#				-> R_X86_64_TLSDESC	sG1
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD, desc first
+ +[0-9a-f]+:	48 8d 05 84 02 10 00[ 	]+lea    1049220\(%rip\),%rax +# 1006c8 <.*>
+#				-> R_X86_64_TLSDESC	sG2
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	66 48 8d 3d 1e 02 10[ 	]+lea    1049118\(%rip\),%rdi +# 100670 <.*>
+ +[0-9a-f]+:	00 *
+#				-> R_X86_64_DTPMOD64	sG2
+ +[0-9a-f]+:	66[ 	]+data16
+ +[0-9a-f]+:	66[ 	]+data16
+ +[0-9a-f]+:	48 e8 6e ff ff ff[ 	]+rex64 callq  [0-9a-f]+ <.*>
+#				-> R_X86_64_JUMP_SLOT	__tls_get_addr
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD -> IE, gd first, after IE use
+ +[0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	48 03 05 f2 01 10 00[ 	]+add    1049074\(%rip\),%rax +# 100660 <.*>
+#				-> R_X86_64_TPOFF64	sG3
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8b 05 e7 01 10 00[ 	]+mov    1049063\(%rip\),%rax +# 100660 <.*>
+#				-> R_X86_64_TPOFF64	sG3
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD -> IE, desc first, after IE use
+ +[0-9a-f]+:	48 8b 05 fa 01 10 00[ 	]+mov    1049082\(%rip\),%rax +# 100680 <.*>
+#				-> R_X86_64_TPOFF64	sG4
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	48 03 05 e4 01 10 00[ 	]+add    1049060\(%rip\),%rax +# 100680 <.*>
+#				-> R_X86_64_TPOFF64	sG4
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD -> IE, gd first, before IE use
+ +[0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	48 03 05 b8 01 10 00[ 	]+add    1049016\(%rip\),%rax +# 100668 <.*>
+#				-> R_X86_64_TPOFF64	sG5
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8b 05 ad 01 10 00[ 	]+mov    1049005\(%rip\),%rax +# 100668 <.*>
+#				-> R_X86_64_TPOFF64	sG5
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD -> IE, desc first, before IE use
+ +[0-9a-f]+:	48 8b 05 c0 01 10 00[ 	]+mov    1049024\(%rip\),%rax +# 100688 <.*>
+#				-> R_X86_64_TPOFF64	sG6
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	48 03 05 aa 01 10 00[ 	]+add    1049002\(%rip\),%rax +# 100688 <.*>
+#				-> R_X86_64_TPOFF64	sG6
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# IE
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 74 01 10 00[ 	]+add    1048948\(%rip\),%rcx +# 100668 <.*>
+#				-> R_X86_64_TPOFF64	sG5
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# IE
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 7e 01 10 00[ 	]+add    1048958\(%rip\),%rcx +# 100688 <.*>
+#				-> R_X86_64_TPOFF64	sG6
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	c9[ 	]+leaveq *
+ +[0-9a-f]+:	c3[ 	]+retq *
Index: ld/testsuite/ld-x86-64/tlsgdesc.rd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsgdesc.rd
diff -N ld/testsuite/ld-x86-64/tlsgdesc.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsgdesc.rd 15 Sep 2005 22:39:29 -0000
@@ -0,0 +1,107 @@
+#source: tlsgdesc.s
+#as: --64
+#ld: -shared -melf64_x86_64
+#readelf: -WSsrl
+#target: x86_64-*-*
+
+There are [0-9]+ section headers, starting at offset 0x.*:
+
+Section Headers:
+  \[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+  \[ 1\] \.hash +.*
+  \[ 2\] \.dynsym +.*
+  \[ 3\] \.dynstr +.*
+  \[ 4\] \.rela.dyn +.*
+  \[ 5\] \.rela.plt +.*
+  \[ 6\] \.plt +.*
+  \[ 7\] \.text +.*
+  \[ 8\] \.dynamic +.*
+  \[ 9\] \.got +.*
+  \[10\] \.got.plt +.*
+  \[11\] \.shstrtab +.*
+  \[12\] \.symtab +.*
+  \[13\] \.strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x[0-9a-f]+
+There are [0-9]+ program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  LOAD.*
+  LOAD.*
+  DYNAMIC.*
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +.hash .dynsym .dynstr .rela.dyn .rela.plt .plt .text *
+   01 +.dynamic .got .got.plt *
+   02 +.dynamic *
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 8 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+[0-9a-f]+  0+200000012 R_X86_64_TPOFF64 +0+ sG3 \+ 0
+[0-9a-f]+  0+300000012 R_X86_64_TPOFF64 +0+ sG5 \+ 0
+[0-9a-f]+  0+400000010 R_X86_64_DTPMOD64 +0+ sG2 \+ 0
+[0-9a-f]+  0+400000011 R_X86_64_DTPOFF64 +0+ sG2 \+ 0
+[0-9a-f]+  0+500000012 R_X86_64_TPOFF64 +0+ sG4 \+ 0
+[0-9a-f]+  0+800000012 R_X86_64_TPOFF64 +0+ sG6 \+ 0
+[0-9a-f]+  0+a00000010 R_X86_64_DTPMOD64 +0+ sG1 \+ 0
+[0-9a-f]+  0+a00000011 R_X86_64_DTPOFF64 +0+ sG1 \+ 0
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 3 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+[0-9a-f]+  0+600000007 R_X86_64_JUMP_SLOT +0+ __tls_get_addr \+ 0
+[0-9a-f]+  0+a0000001c R_X86_64_TLSDESC +0+ sG1 \+ 0
+[0-9a-f]+  0+40000001c R_X86_64_TLSDESC +0+ sG2 \+ 0
+
+Symbol table '.dynsym' contains 13 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_addr
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 27 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _DYNAMIC
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_addr
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
Index: ld/testsuite/ld-x86-64/tlsgdesc.s
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsgdesc.s
diff -N ld/testsuite/ld-x86-64/tlsgdesc.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsgdesc.s 15 Sep 2005 22:39:29 -0000
@@ -0,0 +1,106 @@
+	.text
+	.globl	fc1
+	.type	fc1,@function
+fc1:
+	pushq	%rbp
+	movq	%rsp, %rbp
+	nop;nop;nop;nop
+
+	/* IE against global var.  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sG3@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* IE against global var.  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sG4@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* GD, gd first.  */
+	.byte	0x66
+	leaq	sG1@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+	
+	leaq	sG1@tlsdesc(%rip), %rax
+	call	*sG1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD, desc first.  */
+	leaq	sG2@tlsdesc(%rip), %rax
+	call	*sG2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	.byte	0x66
+	leaq	sG2@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+	
+	/* GD -> IE, gd first, after IE use.  */
+	.byte	0x66
+	leaq	sG3@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+	
+	leaq	sG3@tlsdesc(%rip), %rax
+	call	*sG3@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE, desc first, after IE use.  */
+	leaq	sG4@tlsdesc(%rip), %rax
+	call	*sG4@tlscall(%rax)
+	nop;nop;nop;nop
+
+	.byte	0x66
+	leaq	sG4@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+	
+	/* GD -> IE, gd first, before IE use.  */
+	.byte	0x66
+	leaq	sG5@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+	
+	leaq	sG5@tlsdesc(%rip), %rax
+	call	*sG5@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE, desc first, before IE use.  */
+	leaq	sG6@tlsdesc(%rip), %rax
+	call	*sG6@tlscall(%rax)
+	nop;nop;nop;nop
+
+	.byte	0x66
+	leaq	sG6@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+	
+	/* IE against global var.  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sG5@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* IE against global var.  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sG6@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	leave
+	ret
Index: ld/testsuite/ld-x86-64/x86-64.exp
===================================================================
RCS file: /cvs/uberbaum/./ld/testsuite/ld-x86-64/x86-64.exp,v
retrieving revision 1.4
diff -u -p -r1.4 x86-64.exp
--- ld/testsuite/ld-x86-64/x86-64.exp 18 Jul 2005 06:23:40 -0000 1.4
+++ ld/testsuite/ld-x86-64/x86-64.exp 15 Sep 2005 22:39:29 -0000
@@ -1,5 +1,5 @@
 # Expect script for ld-x86_64 tests
-#   Copyright (C) 2002 Free Software Foundation
+#   Copyright (C) 2002, 2005 Free Software Foundation
 #
 # This file is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -39,6 +39,11 @@ set x86_64tests {
      {{readelf -WSsrl tlspic.rd} {objdump -drj.text tlspic.dd}
       {objdump -sj.got tlspic.sd} {objdump -sj.tdata tlspic.td}}
       "libtlspic.so"}
+    {"TLS descriptor -fpic -shared transitions" "-shared -melf_x86_64"
+     "--64" {tlsdesc.s tlspic2.s}
+     {{readelf -WSsrld tlsdesc.rd} {objdump -drj.text tlsdesc.dd}
+      {objdump "-s -j.got -j.got.plt" tlsdesc.sd} {objdump -sj.tdata tlsdesc.td}
+      {objdump -drj.plt tlsdesc.pd}} "libtlsdesc.so"}
     {"Helper shared library" "-shared -melf_x86_64"
      "--64" {tlslib.s} {} "libtlslib.so"}
     {"TLS -fpic and -fno-pic exec transitions"
@@ -46,6 +51,15 @@ set x86_64tests {
      {{readelf -WSsrl tlsbin.rd} {objdump -drj.text tlsbin.dd}
       {objdump -sj.got tlsbin.sd} {objdump -sj.tdata tlsbin.td}}
       "tlsbin"}
+    {"TLS descriptor -fpic and -fno-pic exec transitions"
+     "-melf_x86_64 tmpdir/libtlslib.so" "--64" {tlsbindesc.s tlsbin.s}
+     {{readelf -WSsrl tlsbindesc.rd} {objdump -drj.text tlsbindesc.dd}
+      {objdump -sj.got tlsbindesc.sd} {objdump -sj.tdata tlsbindesc.td}}
+      "tlsbindesc"}
+    {"TLS with global dynamic and descriptors"
+	"-shared -melf_x86_64" "--64" {tlsgdesc.s}
+     {{readelf -WSsrl tlsgdesc.rd} {objdump -drj.text tlsgdesc.dd}}
+      "libtlsgdesc.so"}
     {"TLS in debug sections" "-melf_x86_64"
      "--64" {tlsg.s}
      {{objdump -sj.debug_foobar tlsg.sd}} "tlsg"}

[-- Attachment #3: Type: text/plain, Size: 188 bytes --]


-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: RFC: TLS improvements for IA32 and AMD64/EM64T
  2005-09-16  7:27 ` Alexandre Oliva
@ 2005-09-16  7:34   ` Andreas Jaeger
  2005-09-16  8:19     ` Jan Beulich
  2005-09-18 17:17   ` Alexandre Oliva
  1 sibling, 1 reply; 17+ messages in thread
From: Andreas Jaeger @ 2005-09-16  7:34 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: binutils

[-- Attachment #1: Type: text/plain, Size: 1675 bytes --]

Alexandre Oliva <aoliva@redhat.com> writes:

> Index: include/elf/x86-64.h
> ===================================================================
> RCS file: /cvs/uberbaum/./include/elf/x86-64.h,v
> retrieving revision 1.8
> diff -u -p -r1.8 x86-64.h
> --- include/elf/x86-64.h 25 Jul 2005 15:41:07 -0000 1.8
> +++ include/elf/x86-64.h 15 Sep 2005 22:39:19 -0000
> @@ -1,5 +1,5 @@
>  /* x86_64 ELF support for BFD.
> -   Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
> +   Copyright (C) 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
>     Contributed by Jan Hubicka <jh@suse.cz>
>  
>     This file is part of BFD, the Binary File Descriptor library.
> @@ -53,6 +53,13 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_ty
>       RELOC_NUMBER (R_X86_64_GOTOFF64, 25)     /* 64 bit offset to GOT */
>       RELOC_NUMBER (R_X86_64_GOTPC32,  26)     /* 32 bit signed pc relative
>                                                   offset to GOT */
> +     RELOC_NUMBER (R_X86_64_GOTPC32_TLSDESC, 27)
> +					      /* 32 bit signed pc relative
> +						 offset to TLS descriptor
> +						 in the GOT.  */
> +     RELOC_NUMBER (R_X86_64_TLSDESC, 28)      /* 2x64-bit TLS descriptor.  */
> +     RELOC_NUMBER (R_X86_64_TLSDESC_CALL, 29) /* Relaxable call through TLS
> +						 descriptor.  */

Please check the current x86-64 ABI, the relocations until 31 are all
taken and reserved, you cannot use the above ones,

Andreas
-- 
 Andreas Jaeger, aj@suse.de, http://www.suse.de/~aj
  SUSE Linux Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
   GPG fingerprint = 93A3 365E CE47 B889 DF7F  FED1 389A 563C C272 A126

[-- Attachment #2: Type: application/pgp-signature, Size: 188 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: RFC: TLS improvements for IA32 and AMD64/EM64T
  2005-09-16  7:34   ` Andreas Jaeger
@ 2005-09-16  8:19     ` Jan Beulich
  2005-09-16 21:01       ` Alexandre Oliva
  0 siblings, 1 reply; 17+ messages in thread
From: Jan Beulich @ 2005-09-16  8:19 UTC (permalink / raw)
  To: Alexandre Oliva, Andreas Jaeger; +Cc: binutils

>Please check the current x86-64 ABI, the relocations until 31 are all
>taken and reserved, you cannot use the above ones,

It's actually 33 meanwhile. And the same proposal that adds 32 and 33
to x86-64 also suggests using 38 on i386 for a different purpose. See
the thread starting at
http://www.x86-64.org/mailing_lists/list?listname=discuss&listnum=0

Jan

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: RFC: TLS improvements for IA32 and AMD64/EM64T
  2005-09-16  8:19     ` Jan Beulich
@ 2005-09-16 21:01       ` Alexandre Oliva
  0 siblings, 0 replies; 17+ messages in thread
From: Alexandre Oliva @ 2005-09-16 21:01 UTC (permalink / raw)
  To: Jan Beulich, Michael Matz, discuss; +Cc: Andreas Jaeger, binutils, libc-alpha

[-- Attachment #1: Type: text/plain, Size: 911 bytes --]

On Sep 16, 2005, "Jan Beulich" <JBeulich@novell.com> wrote:

>> Please check the current x86-64 ABI, the relocations until 31 are all
>> taken and reserved, you cannot use the above ones,

> It's actually 33 meanwhile. And the same proposal that adds 32 and 33
> to x86-64 also suggests using 38 on i386 for a different purpose. See
> the thread starting at
> http://www.x86-64.org/mailing_lists/list?listname=discuss&listnum=0

Thanks, I've renumbered the relocations to avoid conflicts and, while
at that, the dynamic table entries to a more appropriate range.

Here's a patch for the x86-64 ABI document that adds the new
relocations and references the new dynamic table numbers, referring to
the latest version of my specs on the web for details.

I'll post updated patches for binutils and glibc as soon as I get
confirmation that the 3 relocation numbers are at least reserved for
this purpose.

Thanks,


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: tlsdesc.patch --]
[-- Type: text/x-patch, Size: 3126 bytes --]

Index: ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* object-files.tex (Relocation Types): Add
	R_X86_64_GOTPC32_TLSDESC, R_X86_64_TLSDESC_CALL and
	R_X86_64_TLSDESC.  Add pointer to description.
	* dl.tex (Procedure Linkage Table): Mention lazy relocation of TLS
	descriptors.

Index: dl.tex
===================================================================
RCS file: /cvs/Repository/x86-64-ABI/dl.tex,v
retrieving revision 1.31
diff -u -p -r1.31 dl.tex
--- dl.tex 24 Aug 2005 15:11:42 -0000 1.31
+++ dl.tex 16 Sep 2005 18:10:44 -0000
@@ -265,6 +265,14 @@ evaluates procedure linkage table entrie
 resolution and relocation until the first execution of a table entry.
 \index{procedure linkage table|)}
 
+Relocation entries of type \codeindex{R_X86_64_TLSDESC} may also be
+subject to lazy relocation, using a single entry in the procedure
+linkage table and in the global offset table, at locations given by
+\texttt{DT_TLSDESC_PLT} and \texttt{DT_TLSDESC_GOT}, respectively, as
+described in ``Thread-Local Storage Descriptors for IA32 and
+AMD64/EM64T''\footnote{This document is currently available via
+  \url{http://people.redhat.com/aoliva/writeups/TLS/RFC-TLSDESC-x86.txt}}.
+
 \subsubsection{Large Models}
 
 In the small and medium code models the size of both the PLT and the GOT
Index: object-files.tex
===================================================================
RCS file: /cvs/Repository/x86-64-ABI/object-files.tex,v
retrieving revision 1.36
diff -u -p -r1.36 object-files.tex
--- object-files.tex 14 Sep 2005 22:36:07 -0000 1.36
+++ object-files.tex 16 Sep 2005 18:10:46 -0000
@@ -448,6 +448,9 @@ the relocation addend.
       \texttt{R_X86_64_GOTPC32} & 26 & \textit{word32} & \texttt{GOT + A - P} \\
       \texttt{R_X86_64_SIZE32} & 32 & \textit{word32} & \texttt{Z + A} \\
       \texttt{R_X86_64_SIZE64} & 33 & \textit{word64} & \texttt{Z + A} \\
+      \texttt{R_X86_64_GOTPC32_TLSDESC} & 34 & \textit{word32} &  \\
+      \texttt{R_X86_64_TLSDESC_CALL} & 35 & none &  \\
+      \texttt{R_X86_64_TLSDESC} & 36 & \textit{word64}$\times 2$ & \\
 %      \texttt{R_X86_64_GOT64} & 16 & \textit{word64} & \texttt{G + A} \\
 %      \texttt{R_X86_64_PLT64} & 17 & \textit{word64} & \texttt{L + A - P} \\
     \end{tabular}
@@ -501,7 +504,14 @@ The relocations \texttt{R_X86_64_DPTMOD6
 of the Thread-Local Storage ABI extensions and are documented in the
 document called ``ELF Handling for Thread-Local
 Storage''\footnote{This document is currently available via
-  \url{http://people.redhat.com/drepper/tls.pdf}}\index{Thread-Local Storage}.
+  \url{http://people.redhat.com/drepper/tls.pdf}}\index{Thread-Local
+  Storage}.  The relocations \texttt{R_X86_64_GOTPC32_TLSDESC},
+\texttt{R_X86_64_TLSDESC_CALL} and \texttt{R_X86_64_TLSDESC} are also
+used for Thread-Local Storage, but are not documented there as of this
+writing.  A description can be found in the document ``Thread-Local
+Storage Descriptors for IA32 and AMD64/EM64T''\footnote{This document
+  is currently available via
+  \url{http://people.redhat.com/aoliva/writeups/TLS/RFC-TLSDESC-x86.txt}}.
 
 \end{sloppypar}
 

[-- Attachment #3: Type: text/plain, Size: 188 bytes --]


-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: RFC: TLS improvements for IA32 and AMD64/EM64T
  2005-09-16  7:27 ` Alexandre Oliva
  2005-09-16  7:34   ` Andreas Jaeger
@ 2005-09-18 17:17   ` Alexandre Oliva
  2005-09-22  7:53     ` Alexandre Oliva
  1 sibling, 1 reply; 17+ messages in thread
From: Alexandre Oliva @ 2005-09-18 17:17 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 1972 bytes --]

On Sep 16, 2005, Alexandre Oliva <aoliva@redhat.com> wrote:

> On Sep 16, 2005, Alexandre Oliva <aoliva@redhat.com> wrote:
>> Over the past few months, I've been working on porting to IA32 and
>> AMD64/EM64T the interesting bits of the TLS design I came up with for
>> FR-V, achieving some impressive speedups along with slight code size
>> reductions in the most common cases.

>> Although the design is not set in stone yet, it's fully implemented
>> and functional with patches I'm about to post for binutils, gcc and
>> glibc mainline, as follow-ups to this message, except that the GCC
>> patch will go to gcc-patches, as expected.

> Here's the patch for binutils.

> I'm not entirely happy with two aspects of the patch:

> - the way I managed to emit the `call *(%[er]ax)' instruction from
>   `call *variable@TLSCALL(%[er]ax)', dropping the offset from the
>   instruction but still emitting the relocation, seems fragile to me,
>   but there were not additional bits available to do something
>   cleaner.  Any suggestions on a better approach?

> - local_tlsdesc_gotent is probably too wasteful, since very few of all
>   local symbols are going to require TLS descriptor entries.  I hope
>   this is not too much of a problem, but I could introduce another
>   data structure if people feel strongly about it.


> Also note the several FIXMEs with decisions yet to be made on exact
> instructions to be generated in several cases.  I'm yet to develop
> some means to better evaluate the performance of each alternative, but
> even then, I have limited hardware to test on.  I'd welcome feedback
> from people more familiar with performance features of various
> x86-compatible processors.  Anyone?  Thanks in advance,

> Here's the patch.  Built and tested on x86_64-linux-gnu and
> i686-pc-linux-gnu.  Ok to install?

Updated patch, using different relocation numbers, and different
dynamic table numbers as well.  Same tests run and passed.  Ok to
install?


[-- Attachment #2: binutils-20050917.patch.bz2 --]
[-- Type: application/x-bzip2, Size: 24368 bytes --]

[-- Attachment #3: Type: text/plain, Size: 188 bytes --]


-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: RFC: TLS improvements for IA32 and AMD64/EM64T
  2005-09-18 17:17   ` Alexandre Oliva
@ 2005-09-22  7:53     ` Alexandre Oliva
  2006-01-14 17:58       ` Alexandre Oliva
  0 siblings, 1 reply; 17+ messages in thread
From: Alexandre Oliva @ 2005-09-22  7:53 UTC (permalink / raw)
  To: binutils

On Sep 17, 2005, Alexandre Oliva <aoliva@redhat.com> wrote:

> On Sep 16, 2005, Alexandre Oliva <aoliva@redhat.com> wrote:
>> On Sep 16, 2005, Alexandre Oliva <aoliva@redhat.com> wrote:
>>> Over the past few months, I've been working on porting to IA32 and
>>> AMD64/EM64T the interesting bits of the TLS design I came up with for
>>> FR-V, achieving some impressive speedups along with slight code size
>>> reductions in the most common cases.
>> Here's the patch.  Built and tested on x86_64-linux-gnu and
>> i686-pc-linux-gnu.  Ok to install?

> Updated patch, using different relocation numbers, and different
> dynamic table numbers as well.  Same tests run and passed.  Ok to
> install?

Updated again.  Only significant change is that we no longer emit the
new dynamic table entries on x86-64 if we're linking with -z now,
since then we know we won't be resolving the relocations lazily, and
so the entries are not used at all.

Index: bfd/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Introduce TLS descriptors for i386 and x86_64.
	* reloc.c (BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_386_TLS_DESC,
	BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_X86_64_GOTPC32_TLSDESC,
	BFD_RELOC_X86_64_TLSDESC, BFD_RELOC_X86_64_TLSDESC_CALL): New.
	* libbfd.h, bfd-in2.h: Rebuilt.
	* elf32-i386.c (elf_howto_table): New relocations.
	(R_386_tls): Adjust.
	(elf_i386_reloc_type_lookup): Map new relocations.
	(GOT_TLS_GDESC, GOT_TLS_GD_BOTH_P): New macros.
	(GOT_TLS_GD_P, GOT_TLS_GDESC_P, GOT_TLS_GD_ANY_P): New macros.
	(struct elf_i386_link_hash_entry): Add tlsdesc_got field.
	(struct elf_i386_obj_tdata): Add local_tlsdesc_gotent field.
	(elf_i386_local_tlsdesc_gotent): New macro.
	(struct elf_i386_link_hash_table): Add sgotplt_jump_table_size.
	(elf_i386_compute_jump_table_size): New macro.
	(link_hash_newfunc): Initialize tlsdesc_got.
	(elf_i386_link_hash_table_create): Set sgotplt_jump_table_size.
	(elf_i386_tls_transition): Handle R_386_TLS_GOTDESC and
	R_386_TLS_DESC_CALL.
	(elf_i386_check_relocs): Likewise.  Allocate space for
	local_tlsdesc_gotent.
	(elf_i386_gc_sweep_hook): Handle R_386_TLS_GOTDESC and
	R_386_TLS_DESC_CALL.
	(allocate_dynrelocs): Count function PLT relocations.  Reserve
	space for TLS descriptors and relocations.
	(elf_i386_size_dynamic_sections): Reserve space for TLS
	descriptors and relocations.  Set up sgotplt_jump_table_size.
	Don't zero reloc_count in srelplt.
	(elf_i386_always_size_sections): New.  Set up _TLS_MODULE_BASE_.
	(elf_i386_relocate_section): Handle R_386_TLS_GOTDESC and
	R_386_TLS_DESC_CALL.
	(elf_i386_finish_dynamic_symbol): Use GOT_TLS_GD_ANY_P.
	(elf_backend_always_size_sections): Define.
	* elf64-x86-64.c (x86_64_elf_howto): Add R_X86_64_GOTPC32_TLSDESC,
	R_X86_64_TLSDESC, R_X86_64_TLSDESC_CALL.
	(R_X86_64_standard): Adjust.
	(x86_64_reloc_map): Map new relocs.
	(elf64_x86_64_rtype_to_howto): New, split out of...
	(elf64_x86_64_info_to_howto): ... this function, and...
	(elf64_x86_64_reloc_type_lookup): ... use it to map elf_reloc_val.
	(GOT_TLS_GDESC, GOT_TLS_GD_BOTH_P): New macros.
	(GOT_TLS_GD_P, GOT_TLS_GDESC_P, GOT_TLS_GD_ANY_P): New macros.
	(struct elf64_x86_64_link_hash_entry): Add tlsdesc_got field.
	(struct elf64_x86_64_obj_tdata): Add local_tlsdesc_gotent field.
	(elf64_x86_64_local_tlsdesc_gotent): New macro.
	(struct elf64_x86_64_link_hash_table): Add tlsdesc_plt,
	tlsdesc_got and sgotplt_jump_table_size fields.
	(elf64_x86_64_compute_jump_table_size): New macro.
	(link_hash_newfunc): Initialize tlsdesc_got.
	(elf64_x86_64_link_hash_table_create): Initialize new fields.
	(elf64_x86_64_tls_transition): Handle R_X86_64_GOTPC32_TLSDESC and
	R_X86_64_TLSDESC_CALL.
	(elf64_x86_64_check_relocs): Likewise.  Allocate space for
	local_tlsdesc_gotent.
	(elf64_x86_64_gc_sweep_hook): Handle R_X86_64_GOTPC32_TLSDESC and
	R_X86_64_TLSDESC_CALL.
	(allocate_dynrelocs): Count function PLT relocations.  Reserve
	space for TLS descriptors and relocations.
	(elf64_x86_64_size_dynamic_sections): Reserve space for TLS
	descriptors and relocations.  Set up sgotplt_jump_table_size,
	tlsdesc_plt and tlsdesc_got.  Make room for them.  Don't zero
	reloc_count in srelplt.  Add dynamic entries for DT_TLSDESC_PLT
	and DT_TLSDESC_GOT.
	(elf64_x86_64_always_size_sections): New.  Set up
	_TLS_MODULE_BASE_.
	(elf64_x86_64_relocate_section): Handle R_386_TLS_GOTDESC and
	R_386_TLS_DESC_CALL.
	(elf64_x86_64_finish_dynamic_symbol): Use GOT_TLS_GD_ANY_P.
	(elf64_x86_64_finish_dynamic_sections): Set DT_TLSDESC_PLT and
	DT_TLSDESC_GOT.  Set up TLS descriptor lazy resolver PLT entry.
	(elf_backend_always_size_sections): Define.

Index: binutils/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Introduce TLS descriptors for i386 and x86_64.
	* readelf.c (get_dynamic_type): Handle DT_TLSDESC_GOT and
	DT_TLSDESC_PLT.

Index: gas/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Introduce TLS descriptors for i386 and x86_64.
	* config/tc-i386.c (tc_i386_fix_adjustable): Handle
	BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_386_TLS_DESC_CALL,
	BFD_RELOC_X86_64_GOTPC32_TLSDESC, BFD_RELOC_X86_64_TLSDESC_CALL.
	(optimize_disp): Emit fix up for BFD_RELOC_386_TLS_DESC_CALL and
	BFD_RELOC_X86_64_TLSDESC_CALL immediately, and clear the
	displacement bits.
	(build_modrm_byte): Set up zero modrm for TLS desc calls.
	(lex_got): Handle @tlsdesc and @tlscall.
	(md_apply_fix, tc_gen_reloc): Handle the new relocations.

Index: include/elf/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Introduce TLS descriptors for i386 and x86_64.
	* common.h (DT_TLSDESC_GOT, DT_TLSDESC_PLT): New.
	* i386.h (R_386_TLS_GOTDESC, R_386_TLS_DESC_CALL, R_386_TLS_DESC):
	New.
	* x86-64.h (R_X86_64_GOTPC32_TLSDESC, R_X86_64_TLSDESC_CALL,
	R_X86_64_TLSDESC): New.

Index: ld/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Introduce TLS descriptors for i386 and x86_64.
	* ld-i386/i386.exp: Run on x86_64-*-linux* and amd64-*-linux*.
	Add new tests.
	* ld-i386/pcrel16.d: Add -melf_i386.
	* ld-i386/pcrel8.d: Likewise.
	* ld-i386/tlsbindesc.dd: New.
	* ld-i386/tlsbindesc.rd: New.
	* ld-i386/tlsbindesc.s: New.
	* ld-i386/tlsbindesc.sd: New.
	* ld-i386/tlsbindesc.td: New.
	* ld-i386/tlsdesc.dd: New.
	* ld-i386/tlsdesc.rd: New.
	* ld-i386/tlsdesc.s: New.
	* ld-i386/tlsdesc.sd: New.
	* ld-i386/tlsdesc.td: New.
	* ld-i386/tlsgdesc.dd: New.
	* ld-i386/tlsgdesc.rd: New.
	* ld-i386/tlsgdesc.s: New.
	* ld-x86-64/x86-64.exp: Run new tests.
	* ld-x86-64/tlsbindesc.dd: New.
	* ld-x86-64/tlsbindesc.rd: New.
	* ld-x86-64/tlsbindesc.s: New.
	* ld-x86-64/tlsbindesc.sd: New.
	* ld-x86-64/tlsbindesc.td: New.
	* ld-x86-64/tlsdesc.dd: New.
	* ld-x86-64/tlsdesc.pd: New.
	* ld-x86-64/tlsdesc.rd: New.
	* ld-x86-64/tlsdesc.s: New.
	* ld-x86-64/tlsdesc.sd: New.
	* ld-x86-64/tlsdesc.td: New.
	* ld-x86-64/tlsgdesc.dd: New.
	* ld-x86-64/tlsgdesc.rd: New.
	* ld-x86-64/tlsgdesc.s: New.

Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/uberbaum/./bfd/bfd-in2.h,v
retrieving revision 1.366
diff -u -p -r1.366 bfd-in2.h
--- bfd/bfd-in2.h 8 Sep 2005 12:49:18 -0000 1.366
+++ bfd/bfd-in2.h 21 Sep 2005 06:12:08 -0000
@@ -2647,6 +2647,9 @@ in the instruction.  */
   BFD_RELOC_386_TLS_DTPMOD32,
   BFD_RELOC_386_TLS_DTPOFF32,
   BFD_RELOC_386_TLS_TPOFF32,
+  BFD_RELOC_386_TLS_GOTDESC,
+  BFD_RELOC_386_TLS_DESC_CALL,
+  BFD_RELOC_386_TLS_DESC,
 
 /* x86-64/elf relocations  */
   BFD_RELOC_X86_64_GOT32,
@@ -2667,6 +2670,9 @@ in the instruction.  */
   BFD_RELOC_X86_64_TPOFF32,
   BFD_RELOC_X86_64_GOTOFF64,
   BFD_RELOC_X86_64_GOTPC32,
+  BFD_RELOC_X86_64_GOTPC32_TLSDESC,
+  BFD_RELOC_X86_64_TLSDESC_CALL,
+  BFD_RELOC_X86_64_TLSDESC,
 
 /* ns32k relocations  */
   BFD_RELOC_NS32K_IMM_8,
Index: bfd/elf32-i386.c
===================================================================
RCS file: /cvs/uberbaum/./bfd/elf32-i386.c,v
retrieving revision 1.149
diff -u -p -r1.149 elf32-i386.c
--- bfd/elf32-i386.c 31 Aug 2005 23:45:45 -0000 1.149
+++ bfd/elf32-i386.c 21 Sep 2005 06:12:10 -0000
@@ -126,9 +126,19 @@ static reloc_howto_type elf_howto_table[
   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),
+  EMPTY_HOWTO (38),
+  HOWTO(R_386_TLS_GOTDESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_386_TLS_GOTDESC",
+	TRUE, 0xffffffff, 0xffffffff, FALSE),
+  HOWTO(R_386_TLS_DESC_CALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
+	bfd_elf_generic_reloc, "R_386_TLS_DESC_CALL",
+	FALSE, 0, 0, FALSE),
+  HOWTO(R_386_TLS_DESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_386_TLS_DESC",
+	TRUE, 0xffffffff, 0xffffffff, FALSE),
 
   /* Another gap.  */
-#define R_386_tls (R_386_TLS_TPOFF32 + 1 - R_386_tls_offset)
+#define R_386_tls (R_386_TLS_DESC + 1 - R_386_tls_offset)
 #define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_tls)
 
 /* GNU extension to record C++ vtable hierarchy.  */
@@ -292,6 +302,18 @@ elf_i386_reloc_type_lookup (bfd *abfd AT
       TRACE ("BFD_RELOC_386_TLS_TPOFF32");
       return &elf_howto_table[R_386_TLS_TPOFF32 - R_386_tls_offset];
 
+    case BFD_RELOC_386_TLS_GOTDESC:
+      TRACE ("BFD_RELOC_386_TLS_GOTDESC");
+      return &elf_howto_table[R_386_TLS_GOTDESC - R_386_tls_offset];
+
+    case BFD_RELOC_386_TLS_DESC_CALL:
+      TRACE ("BFD_RELOC_386_TLS_DESC_CALL");
+      return &elf_howto_table[R_386_TLS_DESC_CALL - R_386_tls_offset];
+
+    case BFD_RELOC_386_TLS_DESC:
+      TRACE ("BFD_RELOC_386_TLS_DESC");
+      return &elf_howto_table[R_386_TLS_DESC - R_386_tls_offset];
+
     case BFD_RELOC_VTABLE_INHERIT:
       TRACE ("BFD_RELOC_VTABLE_INHERIT");
       return &elf_howto_table[R_386_GNU_VTINHERIT - R_386_vt_offset];
@@ -559,7 +581,20 @@ struct elf_i386_link_hash_entry
 #define GOT_TLS_IE_POS	5
 #define GOT_TLS_IE_NEG	6
 #define GOT_TLS_IE_BOTH 7
+#define GOT_TLS_GDESC	8
+#define GOT_TLS_GD_BOTH_P(type)						\
+  ((type) == (GOT_TLS_GD | GOT_TLS_GDESC))
+#define GOT_TLS_GD_P(type)						\
+  ((type) == GOT_TLS_GD || GOT_TLS_GD_BOTH_P (type))
+#define GOT_TLS_GDESC_P(type)						\
+  ((type) == GOT_TLS_GDESC || GOT_TLS_GD_BOTH_P (type))
+#define GOT_TLS_GD_ANY_P(type)						\
+  (GOT_TLS_GD_P (type) || GOT_TLS_GDESC_P (type))
   unsigned char tls_type;
+
+  /* Offset of the GOTPLT entry reserved for the TLS descriptor,
+     starting at the end of the jump table.  */
+  bfd_vma tlsdesc_got;
 };
 
 #define elf_i386_hash_entry(ent) ((struct elf_i386_link_hash_entry *)(ent))
@@ -570,6 +605,9 @@ struct elf_i386_obj_tdata
 
   /* tls_type for each local got entry.  */
   char *local_got_tls_type;
+
+  /* GOTPLT entries for TLS descriptors.  */
+  bfd_vma *local_tlsdesc_gotent;
 };
 
 #define elf_i386_tdata(abfd) \
@@ -578,6 +616,9 @@ struct elf_i386_obj_tdata
 #define elf_i386_local_got_tls_type(abfd) \
   (elf_i386_tdata (abfd)->local_got_tls_type)
 
+#define elf_i386_local_tlsdesc_gotent(abfd) \
+  (elf_i386_tdata (abfd)->local_tlsdesc_gotent)
+
 static bfd_boolean
 elf_i386_mkobject (bfd *abfd)
 {
@@ -620,6 +661,10 @@ struct elf_i386_link_hash_table
     bfd_vma offset;
   } tls_ldm_got;
 
+  /* The amount of space used by the reserved portion of the sgotplt
+     section, plus whatever space is used by the jump slots.  */
+  bfd_vma sgotplt_jump_table_size;
+
   /* Small local sym to section mapping cache.  */
   struct sym_sec_cache sym_sec;
 };
@@ -629,6 +674,9 @@ struct elf_i386_link_hash_table
 #define elf_i386_hash_table(p) \
   ((struct elf_i386_link_hash_table *) ((p)->hash))
 
+#define elf_i386_compute_jump_table_size(htab) \
+  ((htab)->srelplt->reloc_count * 4)
+
 /* Create an entry in an i386 ELF linker hash table.  */
 
 static struct bfd_hash_entry *
@@ -655,6 +703,7 @@ link_hash_newfunc (struct bfd_hash_entry
       eh = (struct elf_i386_link_hash_entry *) entry;
       eh->dyn_relocs = NULL;
       eh->tls_type = GOT_UNKNOWN;
+      eh->tlsdesc_got = (bfd_vma) -1;
     }
 
   return entry;
@@ -686,6 +735,7 @@ elf_i386_link_hash_table_create (bfd *ab
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
   ret->tls_ldm_got.refcount = 0;
+  ret->sgotplt_jump_table_size = 0;
   ret->sym_sec.abfd = NULL;
   ret->is_vxworks = 0;
   ret->srelplt2 = NULL;
@@ -848,6 +898,8 @@ elf_i386_tls_transition (struct bfd_link
   switch (r_type)
     {
     case R_386_TLS_GD:
+    case R_386_TLS_GOTDESC:
+    case R_386_TLS_DESC_CALL:
     case R_386_TLS_IE_32:
       if (is_local)
 	return R_386_TLS_LE_32;
@@ -952,6 +1004,8 @@ elf_i386_check_relocs (bfd *abfd,
 
 	case R_386_GOT32:
 	case R_386_TLS_GD:
+	case R_386_TLS_GOTDESC:
+	case R_386_TLS_DESC_CALL:
 	  /* This symbol requires a global offset table entry.  */
 	  {
 	    int tls_type, old_tls_type;
@@ -961,6 +1015,9 @@ elf_i386_check_relocs (bfd *abfd,
 	      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_GOTDESC:
+	      case R_386_TLS_DESC_CALL:
+		tls_type = GOT_TLS_GDESC; break;
 	      case R_386_TLS_IE_32:
 		if (ELF32_R_TYPE (rel->r_info) == r_type)
 		  tls_type = GOT_TLS_IE_NEG;
@@ -990,13 +1047,16 @@ elf_i386_check_relocs (bfd *abfd,
 		    bfd_size_type size;
 
 		    size = symtab_hdr->sh_info;
-		    size *= (sizeof (bfd_signed_vma) + sizeof(char));
+		    size *= (sizeof (bfd_signed_vma)
+			     + sizeof (bfd_vma) + sizeof(char));
 		    local_got_refcounts = bfd_zalloc (abfd, size);
 		    if (local_got_refcounts == NULL)
 		      return FALSE;
 		    elf_local_got_refcounts (abfd) = local_got_refcounts;
+		    elf_i386_local_tlsdesc_gotent (abfd)
+		      = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info);
 		    elf_i386_local_got_tls_type (abfd)
-		      = (char *) (local_got_refcounts + symtab_hdr->sh_info);
+		      = (char *) (local_got_refcounts + 2 * symtab_hdr->sh_info);
 		  }
 		local_got_refcounts[r_symndx] += 1;
 		old_tls_type = elf_i386_local_got_tls_type (abfd) [r_symndx];
@@ -1007,11 +1067,14 @@ elf_i386_check_relocs (bfd *abfd,
 	    /* If a TLS symbol is accessed using IE at least once,
 	       there is no point to use dynamic model for it.  */
 	    else if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN
-		     && (old_tls_type != GOT_TLS_GD
+		     && (! GOT_TLS_GD_ANY_P (old_tls_type)
 			 || (tls_type & GOT_TLS_IE) == 0))
 	      {
-		if ((old_tls_type & GOT_TLS_IE) && tls_type == GOT_TLS_GD)
+		if ((old_tls_type & GOT_TLS_IE) && GOT_TLS_GD_ANY_P (tls_type))
 		  tls_type = old_tls_type;
+		else if (GOT_TLS_GD_ANY_P (old_tls_type)
+			 && GOT_TLS_GD_ANY_P (tls_type))
+		  tls_type |= old_tls_type;
 		else
 		  {
 		    (*_bfd_error_handler)
@@ -1319,6 +1382,8 @@ elf_i386_gc_sweep_hook (bfd *abfd,
 	  break;
 
 	case R_386_TLS_GD:
+	case R_386_TLS_GOTDESC:
+	case R_386_TLS_DESC_CALL:
 	case R_386_TLS_IE_32:
 	case R_386_TLS_IE:
 	case R_386_TLS_GOTIE:
@@ -1582,6 +1647,7 @@ allocate_dynrelocs (struct elf_link_hash
 
 	  /* We also need to make an entry in the .rel.plt section.  */
 	  htab->srelplt->size += sizeof (Elf32_External_Rel);
+	  htab->srelplt->reloc_count++;
 
 	  if (htab->is_vxworks && !info->shared)
 	    {
@@ -1615,6 +1681,9 @@ allocate_dynrelocs (struct elf_link_hash
       h->needs_plt = 0;
     }
 
+  eh = (struct elf_i386_link_hash_entry *) h;
+  eh->tlsdesc_got = (bfd_vma) -1;
+
   /* If R_386_TLS_{IE_32,IE,GOTIE} symbol is now local to the binary,
      make it a R_386_TLS_LE_32 requiring no TLS entry.  */
   if (h->got.refcount > 0
@@ -1638,11 +1707,22 @@ allocate_dynrelocs (struct elf_link_hash
 	}
 
       s = htab->sgot;
-      h->got.offset = s->size;
-      s->size += 4;
-      /* R_386_TLS_GD needs 2 consecutive GOT slots.  */
-      if (tls_type == GOT_TLS_GD || tls_type == GOT_TLS_IE_BOTH)
-	s->size += 4;
+      if (GOT_TLS_GDESC_P (tls_type))
+	{
+	  eh->tlsdesc_got = htab->sgotplt->size
+	    - elf_i386_compute_jump_table_size (htab);
+	  htab->sgotplt->size += 8;
+	  h->got.offset = (bfd_vma) -2;
+	}
+      if (! GOT_TLS_GDESC_P (tls_type)
+	  || GOT_TLS_GD_P (tls_type))
+	{
+	  h->got.offset = s->size;
+	  s->size += 4;
+	  /* R_386_TLS_GD needs 2 consecutive GOT slots.  */
+	  if (GOT_TLS_GD_P (tls_type) || tls_type == GOT_TLS_IE_BOTH)
+	    s->size += 4;
+	}
       dyn = htab->elf.dynamic_sections_created;
       /* R_386_TLS_IE_32 needs one dynamic relocation,
 	 R_386_TLS_IE resp. R_386_TLS_GOTIE needs one dynamic relocation,
@@ -1651,21 +1731,23 @@ allocate_dynrelocs (struct elf_link_hash
 	 global.  */
       if (tls_type == GOT_TLS_IE_BOTH)
 	htab->srelgot->size += 2 * sizeof (Elf32_External_Rel);
-      else if ((tls_type == GOT_TLS_GD && h->dynindx == -1)
+      else if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1)
 	       || (tls_type & GOT_TLS_IE))
 	htab->srelgot->size += sizeof (Elf32_External_Rel);
-      else if (tls_type == GOT_TLS_GD)
+      else if (GOT_TLS_GD_P (tls_type))
 	htab->srelgot->size += 2 * sizeof (Elf32_External_Rel);
-      else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-		|| h->root.type != bfd_link_hash_undefweak)
+      else if (! GOT_TLS_GDESC_P (tls_type)
+	       && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+		   || h->root.type != bfd_link_hash_undefweak)
 	       && (info->shared
 		   || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
 	htab->srelgot->size += sizeof (Elf32_External_Rel);
+      if (GOT_TLS_GDESC_P (tls_type))
+	htab->srelplt->size += sizeof (Elf32_External_Rel);
     }
   else
     h->got.offset = (bfd_vma) -1;
 
-  eh = (struct elf_i386_link_hash_entry *) h;
   if (eh->dyn_relocs == NULL)
     return TRUE;
 
@@ -1813,6 +1895,7 @@ elf_i386_size_dynamic_sections (bfd *out
       bfd_signed_vma *local_got;
       bfd_signed_vma *end_local_got;
       char *local_tls_type;
+      bfd_vma *local_tlsdesc_gotent;
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
       asection *srel;
@@ -1855,25 +1938,42 @@ elf_i386_size_dynamic_sections (bfd *out
       locsymcount = symtab_hdr->sh_info;
       end_local_got = local_got + locsymcount;
       local_tls_type = elf_i386_local_got_tls_type (ibfd);
+      local_tlsdesc_gotent = elf_i386_local_tlsdesc_gotent (ibfd);
       s = htab->sgot;
       srel = htab->srelgot;
-      for (; local_got < end_local_got; ++local_got, ++local_tls_type)
+      for (; local_got < end_local_got;
+	   ++local_got, ++local_tls_type, ++local_tlsdesc_gotent)
 	{
+	  *local_tlsdesc_gotent = (bfd_vma) -1;
 	  if (*local_got > 0)
 	    {
-	      *local_got = s->size;
-	      s->size += 4;
-	      if (*local_tls_type == GOT_TLS_GD
-		  || *local_tls_type == GOT_TLS_IE_BOTH)
-		s->size += 4;
+	      if (GOT_TLS_GDESC_P (*local_tls_type))
+		{
+		  *local_tlsdesc_gotent = htab->sgotplt->size
+		    - elf_i386_compute_jump_table_size (htab);
+		  htab->sgotplt->size += 8;
+		  *local_got = (bfd_vma) -2;
+		}
+	      if (! GOT_TLS_GDESC_P (*local_tls_type)
+		  || GOT_TLS_GD_P (*local_tls_type))
+		{
+		  *local_got = s->size;
+		  s->size += 4;
+		  if (GOT_TLS_GD_P (*local_tls_type)
+		      || *local_tls_type == GOT_TLS_IE_BOTH)
+		    s->size += 4;
+		}
 	      if (info->shared
-		  || *local_tls_type == GOT_TLS_GD
+		  || GOT_TLS_GD_ANY_P (*local_tls_type)
 		  || (*local_tls_type & GOT_TLS_IE))
 		{
 		  if (*local_tls_type == GOT_TLS_IE_BOTH)
 		    srel->size += 2 * sizeof (Elf32_External_Rel);
-		  else
+		  else if (GOT_TLS_GD_P (*local_tls_type)
+			   || ! GOT_TLS_GDESC_P (*local_tls_type))
 		    srel->size += sizeof (Elf32_External_Rel);
+		  if (GOT_TLS_GDESC_P (*local_tls_type))
+		    htab->srelplt->size += sizeof (Elf32_External_Rel);
 		}
 	    }
 	  else
@@ -1917,6 +2017,14 @@ elf_i386_size_dynamic_sections (bfd *out
      sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
 
+  /* For every jump slot reserved in the sgotplt, reloc_count is
+     incremented.  However, when we reserve space for TLS descriptors,
+     it's not incremented, so in order to compute the space reserved
+     for them, it suffices to multiply the reloc count by the jump
+     slot size.  */
+  if (htab->srelplt)
+    htab->sgotplt_jump_table_size = htab->srelplt->reloc_count * 4;
+
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
   relocs = FALSE;
@@ -1948,7 +2056,8 @@ elf_i386_size_dynamic_sections (bfd *out
 
 	  /* We use the reloc_count field as a counter if we need
 	     to copy relocs into the output file.  */
-	  s->reloc_count = 0;
+	  if (s != htab->srelplt)
+	    s->reloc_count = 0;
 	}
       else
 	{
@@ -2035,6 +2144,41 @@ elf_i386_size_dynamic_sections (bfd *out
   return TRUE;
 }
 
+static bfd_boolean
+elf_i386_always_size_sections (bfd *output_bfd,
+			       struct bfd_link_info *info)
+{
+  asection *tls_sec = elf_hash_table (info)->tls_sec;
+
+  if (tls_sec)
+    {
+      struct elf_link_hash_entry *tlsbase;
+
+      tlsbase = elf_link_hash_lookup (elf_hash_table (info),
+				      "_TLS_MODULE_BASE_",
+				      FALSE, FALSE, FALSE);
+
+      if (tlsbase && tlsbase->type == STT_TLS)
+	{
+	  struct bfd_link_hash_entry *bh = NULL;
+	  const struct elf_backend_data *bed
+	    = get_elf_backend_data (output_bfd);
+
+	  if (!(_bfd_generic_link_add_one_symbol
+		(info, output_bfd, "_TLS_MODULE_BASE_", BSF_LOCAL,
+		 tls_sec, 0, NULL, FALSE,
+		 bed->collect, &bh)))
+	    return FALSE;
+	  tlsbase = (struct elf_link_hash_entry *)bh;
+	  tlsbase->def_regular = 1;
+	  tlsbase->other = STV_HIDDEN;
+	  (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE);
+	}
+    }
+
+  return TRUE;
+}
+
 /* Set the correct type for an x86 ELF section.  We do this by the
    section name, which is a hack, but ought to work.  */
 
@@ -2112,6 +2256,7 @@ elf_i386_relocate_section (bfd *output_b
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
   bfd_vma *local_got_offsets;
+  bfd_vma *local_tlsdesc_gotents;
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
 
@@ -2119,6 +2264,7 @@ elf_i386_relocate_section (bfd *output_b
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (input_bfd);
   local_got_offsets = elf_local_got_offsets (input_bfd);
+  local_tlsdesc_gotents = elf_i386_local_tlsdesc_gotent (input_bfd);
 
   rel = relocs;
   relend = relocs + input_section->reloc_count;
@@ -2130,7 +2276,7 @@ elf_i386_relocate_section (bfd *output_b
       struct elf_link_hash_entry *h;
       Elf_Internal_Sym *sym;
       asection *sec;
-      bfd_vma off;
+      bfd_vma off, offplt;
       bfd_vma relocation;
       bfd_boolean unresolved_reloc;
       bfd_reloc_status_type r;
@@ -2552,6 +2698,8 @@ elf_i386_relocate_section (bfd *output_b
 	  /* Fall through */
 
 	case R_386_TLS_GD:
+	case R_386_TLS_GOTDESC:
+	case R_386_TLS_DESC_CALL:
 	case R_386_TLS_IE_32:
 	case R_386_TLS_GOTIE:
 	  r_type = elf_i386_tls_transition (info, r_type, h == NULL);
@@ -2566,7 +2714,9 @@ elf_i386_relocate_section (bfd *output_b
 	    }
 	  if (tls_type == GOT_TLS_IE)
 	    tls_type = GOT_TLS_IE_NEG;
-	  if (r_type == R_386_TLS_GD)
+	  if (r_type == R_386_TLS_GD
+	      || r_type == R_386_TLS_GOTDESC
+	      || r_type == R_386_TLS_DESC_CALL)
 	    {
 	      if (tls_type == GOT_TLS_IE_POS)
 		r_type = R_386_TLS_GOTIE;
@@ -2640,6 +2790,67 @@ elf_i386_relocate_section (bfd *output_b
 		  rel++;
 		  continue;
 		}
+	      else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC)
+		{
+		  /* GDesc -> LE transition.
+		     It's originally something like:
+		     leal x@tlsdesc(%ebx), %eax
+
+		     aoliva FIXME.  Decide whether to change it to:
+		     gs: .byte 0x65 ; movl $x@ntpoff, %eax
+		     or
+		     leal x@ntpoff, %eax
+		     
+		     Registers other than %eax may be set up here.  */
+		  
+		  unsigned int val, type;
+		  bfd_vma roff;
+
+		  /* First, make sure it's a leal adding ebx to a
+		     32-bit offset into any register, although it's
+		     probably almost always going to be eax.  */
+		  roff = rel->r_offset;
+		  BFD_ASSERT (roff >= 2);
+		  type = bfd_get_8 (input_bfd, contents + roff - 2);
+		  BFD_ASSERT (type == 0x8d);
+		  val = bfd_get_8 (input_bfd, contents + roff - 1);
+		  BFD_ASSERT ((val & 0xc7) == 0x83);
+		  BFD_ASSERT (roff + 4 <= input_section->size);
+
+		  /* Now modify the instruction as appropriate.  */
+		  bfd_put_8 (output_bfd, 0x65, contents + roff - 2);
+		  /* aoliva FIXME: remove the above and xor the byte
+		     below with 0x86.  */
+		  bfd_put_8 (output_bfd, 0xb8 | ((val >> 3) & 7),
+			     contents + roff - 1);
+		  bfd_put_32 (output_bfd, -tpoff (info, relocation),
+			      contents + roff);
+		  continue;
+		}
+	      else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL)
+		{
+		  /* GDesc -> LE transition.
+		     It's originally:
+		     call *(%eax)
+		     Turn it into:
+		     movl %eax, %eax  */
+		  
+		  unsigned int val, type;
+		  bfd_vma roff;
+
+		  /* First, make sure it's a call *(%eax).  */
+		  roff = rel->r_offset;
+		  BFD_ASSERT (roff + 2 <= input_section->size);
+		  type = bfd_get_8 (input_bfd, contents + roff);
+		  BFD_ASSERT (type == 0xff);
+		  val = bfd_get_8 (input_bfd, contents + roff + 1);
+		  BFD_ASSERT (val == 0x10);
+
+		  /* Now modify the instruction as appropriate.  */
+		  bfd_put_8 (output_bfd, 0x89, contents + roff);
+		  bfd_put_8 (output_bfd, 0xc0, contents + roff + 1);
+		  continue;
+		}
 	      else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_IE)
 		{
 		  unsigned int val, type;
@@ -2754,13 +2965,17 @@ elf_i386_relocate_section (bfd *output_b
 	    abort ();
 
 	  if (h != NULL)
-	    off = h->got.offset;
+	    {
+	      off = h->got.offset;
+	      offplt = elf_i386_hash_entry (h)->tlsdesc_got;
+	    }
 	  else
 	    {
 	      if (local_got_offsets == NULL)
 		abort ();
 
 	      off = local_got_offsets[r_symndx];
+	      offplt = local_tlsdesc_gotents[r_symndx];
 	    }
 
 	  if ((off & 1) != 0)
@@ -2770,35 +2985,77 @@ elf_i386_relocate_section (bfd *output_b
 	      Elf_Internal_Rela outrel;
 	      bfd_byte *loc;
 	      int dr_type, indx;
+	      asection *sreloc;
 
 	      if (htab->srelgot == NULL)
 		abort ();
 
+	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
+
+	      if (GOT_TLS_GDESC_P (tls_type))
+		{
+		  outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_DESC);
+		  BFD_ASSERT (htab->sgotplt_jump_table_size + offplt + 8
+			      <= htab->sgotplt->size);
+		  outrel.r_offset = (htab->sgotplt->output_section->vma
+				     + htab->sgotplt->output_offset
+				     + offplt
+				     + htab->sgotplt_jump_table_size);
+		  sreloc = htab->srelplt;
+		  loc = sreloc->contents;
+		  loc += sreloc->reloc_count++
+		    * sizeof (Elf32_External_Rel);
+		  BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
+			      <= sreloc->contents + sreloc->size);
+		  bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
+		  if (indx == 0)
+		    {
+		      BFD_ASSERT (! unresolved_reloc);
+		      bfd_put_32 (output_bfd,
+				  relocation - dtpoff_base (info),
+				  htab->sgotplt->contents + offplt
+				  + htab->sgotplt_jump_table_size + 4);
+		    }
+		  else
+		    {
+		      bfd_put_32 (output_bfd, 0,
+				  htab->sgotplt->contents + offplt
+				  + htab->sgotplt_jump_table_size + 4);
+		    }
+		}
+
+	      sreloc = htab->srelgot;
+
 	      outrel.r_offset = (htab->sgot->output_section->vma
 				 + htab->sgot->output_offset + off);
 
-	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
-	      if (r_type == R_386_TLS_GD)
+	      if (GOT_TLS_GD_P (tls_type))
 		dr_type = R_386_TLS_DTPMOD32;
+	      else if (GOT_TLS_GDESC_P (tls_type))
+		goto dr_done;
 	      else if (tls_type == GOT_TLS_IE_POS)
 		dr_type = R_386_TLS_TPOFF;
 	      else
 		dr_type = R_386_TLS_TPOFF32;
+
 	      if (dr_type == R_386_TLS_TPOFF && indx == 0)
 		bfd_put_32 (output_bfd, relocation - dtpoff_base (info),
 			    htab->sgot->contents + off);
 	      else if (dr_type == R_386_TLS_TPOFF32 && indx == 0)
 		bfd_put_32 (output_bfd, dtpoff_base (info) - relocation,
 			    htab->sgot->contents + off);
-	      else
+	      else if (dr_type != R_386_TLS_DESC)
 		bfd_put_32 (output_bfd, 0,
 			    htab->sgot->contents + off);
 	      outrel.r_info = ELF32_R_INFO (indx, dr_type);
-	      loc = htab->srelgot->contents;
-	      loc += htab->srelgot->reloc_count++ * sizeof (Elf32_External_Rel);
+
+	      loc = sreloc->contents;
+	      loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel);
+	      BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
+			  <= sreloc->contents + sreloc->size);
 	      bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
 
-	      if (r_type == R_386_TLS_GD)
+	      if (GOT_TLS_GD_P (tls_type))
 		{
 		  if (indx == 0)
 		    {
@@ -2814,8 +3071,10 @@ elf_i386_relocate_section (bfd *output_b
 		      outrel.r_info = ELF32_R_INFO (indx,
 						    R_386_TLS_DTPOFF32);
 		      outrel.r_offset += 4;
-		      htab->srelgot->reloc_count++;
+		      sreloc->reloc_count++;
 		      loc += sizeof (Elf32_External_Rel);
+		      BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
+				  <= sreloc->contents + sreloc->size);
 		      bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
 		    }
 		}
@@ -2826,25 +3085,33 @@ elf_i386_relocate_section (bfd *output_b
 			      htab->sgot->contents + off + 4);
 		  outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_TPOFF);
 		  outrel.r_offset += 4;
-		  htab->srelgot->reloc_count++;
+		  sreloc->reloc_count++;
 		  loc += sizeof (Elf32_External_Rel);
 		  bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
 		}
 
+	    dr_done:
 	      if (h != NULL)
 		h->got.offset |= 1;
 	      else
 		local_got_offsets[r_symndx] |= 1;
 	    }
 
-	  if (off >= (bfd_vma) -2)
+	  if (off >= (bfd_vma) -2
+	      && ! GOT_TLS_GDESC_P (tls_type))
 	    abort ();
-	  if (r_type == ELF32_R_TYPE (rel->r_info))
+	  if (r_type == R_386_TLS_GOTDESC
+	      || r_type == R_386_TLS_DESC_CALL)
+	    {
+	      relocation = htab->sgotplt_jump_table_size + offplt;
+	      unresolved_reloc = FALSE;
+	    }
+	  else if (r_type == ELF32_R_TYPE (rel->r_info))
 	    {
 	      bfd_vma g_o_t = htab->sgotplt->output_section->vma
 			      + htab->sgotplt->output_offset;
 	      relocation = htab->sgot->output_section->vma
-			   + htab->sgot->output_offset + off - g_o_t;
+		+ htab->sgot->output_offset + off - g_o_t;
 	      if ((r_type == R_386_TLS_IE || r_type == R_386_TLS_GOTIE)
 		  && tls_type == GOT_TLS_IE_BOTH)
 		relocation += 4;
@@ -2852,7 +3119,7 @@ elf_i386_relocate_section (bfd *output_b
 		relocation += g_o_t;
 	      unresolved_reloc = FALSE;
 	    }
-	  else
+	  else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD)
 	    {
 	      unsigned int val, type;
 	      bfd_vma roff;
@@ -2916,6 +3183,97 @@ elf_i386_relocate_section (bfd *output_b
 	      rel++;
 	      continue;
 	    }
+	  else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC)
+	    {
+	      /* GDesc -> IE transition.
+		 It's originally something like:
+		 leal x@tlsdesc(%ebx), %eax
+
+		 aoliva FIXME: decide whether to change it to:
+		 movl x@gotntpoff(%ebx), %eax # before movl %eax,%eax
+		 or
+		 leal x@gotntpoff(%ebx), %eax # before movl (%eax),%eax
+		 but the latter won't work if we need to negate the
+		 loaded value.
+		     
+		 Registers other than %eax may be set up here.  */
+		  
+	      unsigned int val, type;
+	      bfd_vma roff;
+
+	      /* First, make sure it's a leal adding ebx to a 32-bit
+		 offset into any register, although it's probably
+		 almost always going to be eax.  */
+	      roff = rel->r_offset;
+	      BFD_ASSERT (roff >= 2);
+	      type = bfd_get_8 (input_bfd, contents + roff - 2);
+	      BFD_ASSERT (type == 0x8d);
+	      val = bfd_get_8 (input_bfd, contents + roff - 1);
+	      BFD_ASSERT ((val & 0xc7) == 0x83);
+	      BFD_ASSERT (roff + 4 <= input_section->size);
+
+	      /* Now modify the instruction as appropriate.  */
+	      /* To turn a leal into a movl in the form we use it, it
+		 suffices to change the first byte from 0x8d to 0x8b.
+		 aoliva FIXME: should we decide to keep the leal, all
+		 we have to do is remove the statement below, and
+		 adjust the relaxation of R_386_TLS_DESC_CALL.  */
+	      bfd_put_8 (output_bfd, 0x8b, contents + roff - 2);
+
+	      if (tls_type == GOT_TLS_IE_BOTH)
+		off += 4;
+
+	      bfd_put_32 (output_bfd,
+			  htab->sgot->output_section->vma
+			  + htab->sgot->output_offset + off
+			  - htab->sgotplt->output_section->vma
+			  - htab->sgotplt->output_offset,
+			  contents + roff);
+	      continue;
+	    }
+	  else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL)
+	    {
+	      /* GDesc -> IE transition.
+		 It's originally:
+		 calll *(%eax)
+
+		 aoliva FIXME: decide whether to change it to:
+		 movl %eax,%eax # after movl x@gotntpoff(%ebx), %eax
+		 or
+		 movl (%eax),%eax # after leal x@gotntpoff(%ebx), %eax
+
+	         Either one works unless we have to negate the
+	         offset.  */
+		  
+	      unsigned int val, type;
+	      bfd_vma roff;
+
+	      /* First, make sure it's a call *(%eax).  */
+	      roff = rel->r_offset;
+	      BFD_ASSERT (roff + 2 <= input_section->size);
+	      type = bfd_get_8 (input_bfd, contents + roff);
+	      BFD_ASSERT (type == 0xff);
+	      val = bfd_get_8 (input_bfd, contents + roff + 1);
+	      BFD_ASSERT (val == 0x10);
+
+	      /* Now modify the instruction as appropriate.  */
+	      if (tls_type != GOT_TLS_IE_NEG)
+		{
+		  /* movl %eax,%eax */
+		  bfd_put_8 (output_bfd, 0x89, contents + roff);
+		  bfd_put_8 (output_bfd, 0xc0, contents + roff + 1);
+		}
+	      else
+		{
+		  /* negl %eax */
+		  bfd_put_8 (output_bfd, 0xf7, contents + roff);
+		  bfd_put_8 (output_bfd, 0xd8, contents + roff + 1);
+		}
+
+	      continue;
+	    }
+	  else
+	    BFD_ASSERT (FALSE);
 	  break;
 
 	case R_386_TLS_LDM:
@@ -3223,7 +3581,7 @@ elf_i386_finish_dynamic_symbol (bfd *out
     }
 
   if (h->got.offset != (bfd_vma) -1
-      && elf_i386_hash_entry(h)->tls_type != GOT_TLS_GD
+      && ! GOT_TLS_GD_ANY_P (elf_i386_hash_entry(h)->tls_type)
       && (elf_i386_hash_entry(h)->tls_type & GOT_TLS_IE) == 0)
     {
       Elf_Internal_Rela rel;
@@ -3558,6 +3916,7 @@ elf_i386_plt_sym_val (bfd_vma i, const a
 #define elf_backend_reloc_type_class	      elf_i386_reloc_type_class
 #define elf_backend_relocate_section	      elf_i386_relocate_section
 #define elf_backend_size_dynamic_sections     elf_i386_size_dynamic_sections
+#define elf_backend_always_size_sections      elf_i386_always_size_sections
 #define elf_backend_plt_sym_val		      elf_i386_plt_sym_val
 
 #include "elf32-target.h"
Index: bfd/elf64-x86-64.c
===================================================================
RCS file: /cvs/uberbaum/./bfd/elf64-x86-64.c,v
retrieving revision 1.107
diff -u -p -r1.107 elf64-x86-64.c
--- bfd/elf64-x86-64.c 31 Aug 2005 23:45:46 -0000 1.107
+++ bfd/elf64-x86-64.c 21 Sep 2005 06:12:12 -0000
@@ -112,12 +112,31 @@ static reloc_howto_type x86_64_elf_howto
   HOWTO(R_X86_64_GOTPC32, 0, 2, 32, TRUE, 0, complain_overflow_signed,
 	bfd_elf_generic_reloc, "R_X86_64_GOTPC32",
 	FALSE, 0xffffffff, 0xffffffff, TRUE),
+  EMPTY_HOWTO (27),
+  EMPTY_HOWTO (28),
+  EMPTY_HOWTO (29),
+  EMPTY_HOWTO (30),
+  EMPTY_HOWTO (31),
+  EMPTY_HOWTO (32),
+  EMPTY_HOWTO (33),
+  HOWTO(R_X86_64_GOTPC32_TLSDESC, 0, 2, 32, TRUE, 0,
+	complain_overflow_bitfield, bfd_elf_generic_reloc,
+	"R_X86_64_GOTPC32_TLSDESC",
+	FALSE, 0xffffffff, 0xffffffff, TRUE),
+  HOWTO(R_X86_64_TLSDESC_CALL, 0, 0, 0, FALSE, 0,
+	complain_overflow_dont, bfd_elf_generic_reloc,
+	"R_X86_64_TLSDESC_CALL", 
+	FALSE, 0, 0, FALSE),
+  HOWTO(R_X86_64_TLSDESC, 0, 4, 64, FALSE, 0,
+	complain_overflow_bitfield, bfd_elf_generic_reloc,
+	"R_X86_64_TLSDESC",
+	FALSE, MINUS_ONE, MINUS_ONE, FALSE),
 
   /* We have a gap in the reloc numbers here.
      R_X86_64_standard counts the number up to this point, and
      R_X86_64_vt_offset is the value to subtract from a reloc type of
      R_X86_64_GNU_VT* to form an index into this table.  */
-#define R_X86_64_standard (R_X86_64_GOTPC32 + 1)
+#define R_X86_64_standard (R_X86_64_TLSDESC + 1)
 #define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard)
 
 /* GNU extension to record C++ vtable hierarchy.  */
@@ -166,14 +185,38 @@ static const struct elf_reloc_map x86_64
   { BFD_RELOC_64_PCREL,		R_X86_64_PC64, },
   { BFD_RELOC_X86_64_GOTOFF64,	R_X86_64_GOTOFF64, },
   { BFD_RELOC_X86_64_GOTPC32,	R_X86_64_GOTPC32, },
+  { BFD_RELOC_X86_64_GOTPC32_TLSDESC, R_X86_64_GOTPC32_TLSDESC, },
+  { BFD_RELOC_X86_64_TLSDESC_CALL, R_X86_64_TLSDESC_CALL, },
+  { BFD_RELOC_X86_64_TLSDESC,	R_X86_64_TLSDESC, },
   { BFD_RELOC_VTABLE_INHERIT,	R_X86_64_GNU_VTINHERIT, },
   { BFD_RELOC_VTABLE_ENTRY,	R_X86_64_GNU_VTENTRY, },
 };
 
+static reloc_howto_type *
+elf64_x86_64_rtype_to_howto (bfd *abfd, unsigned r_type)
+{
+  unsigned i;
+
+  if (r_type < (unsigned int) R_X86_64_GNU_VTINHERIT
+      || r_type >= (unsigned int) R_X86_64_max)
+    {
+      if (r_type >= (unsigned int) R_X86_64_standard)
+	{
+	  (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
+				 abfd, (int) r_type);
+	  r_type = R_X86_64_NONE;
+	}
+      i = r_type;
+    }
+  else
+    i = r_type - (unsigned int) R_X86_64_vt_offset;
+  BFD_ASSERT (x86_64_elf_howto_table[i].type == r_type);
+  return &x86_64_elf_howto_table[i];
+}
 
 /* Given a BFD reloc type, return a HOWTO structure.  */
 static reloc_howto_type *
-elf64_x86_64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+elf64_x86_64_reloc_type_lookup (bfd *abfd,
 				bfd_reloc_code_real_type code)
 {
   unsigned int i;
@@ -182,7 +225,8 @@ elf64_x86_64_reloc_type_lookup (bfd *abf
        i++)
     {
       if (x86_64_reloc_map[i].bfd_reloc_val == code)
-	return &x86_64_elf_howto_table[i];
+	return elf64_x86_64_rtype_to_howto (abfd,
+					    x86_64_reloc_map[i].elf_reloc_val);
     }
   return 0;
 }
@@ -193,23 +237,10 @@ static void
 elf64_x86_64_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
 			    Elf_Internal_Rela *dst)
 {
-  unsigned r_type, i;
+  unsigned r_type;
 
   r_type = ELF64_R_TYPE (dst->r_info);
-  if (r_type < (unsigned int) R_X86_64_GNU_VTINHERIT
-      || r_type >= (unsigned int) R_X86_64_max)
-    {
-      if (r_type >= (unsigned int) R_X86_64_standard)
-	{
-	  (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
-				 abfd, (int) r_type);
-	  r_type = R_X86_64_NONE;
-	}
-      i = r_type;
-    }
-  else
-    i = r_type - (unsigned int) R_X86_64_vt_offset;
-  cache_ptr->howto = &x86_64_elf_howto_table[i];
+  cache_ptr->howto = elf64_x86_64_rtype_to_howto (abfd, r_type);
   BFD_ASSERT (r_type == cache_ptr->howto->type);
 }
 \f
@@ -353,7 +384,20 @@ struct elf64_x86_64_link_hash_entry
 #define GOT_NORMAL	1
 #define GOT_TLS_GD	2
 #define GOT_TLS_IE	3
+#define GOT_TLS_GDESC	4
+#define GOT_TLS_GD_BOTH_P(type) \
+  ((type) == (GOT_TLS_GD | GOT_TLS_GDESC))
+#define GOT_TLS_GD_P(type) \
+  ((type) == GOT_TLS_GD || GOT_TLS_GD_BOTH_P (type))
+#define GOT_TLS_GDESC_P(type) \
+  ((type) == GOT_TLS_GDESC || GOT_TLS_GD_BOTH_P (type))
+#define GOT_TLS_GD_ANY_P(type) \
+  (GOT_TLS_GD_P (type) || GOT_TLS_GDESC_P (type))
   unsigned char tls_type;
+
+  /* Offset of the GOTPLT entry reserved for the TLS descriptor,
+     starting at the end of the jump table.  */
+  bfd_vma tlsdesc_got;
 };
 
 #define elf64_x86_64_hash_entry(ent) \
@@ -365,6 +409,9 @@ struct elf64_x86_64_obj_tdata
 
   /* tls_type for each local got entry.  */
   char *local_got_tls_type;
+
+  /* GOTPLT entries for TLS descriptors.  */
+  bfd_vma *local_tlsdesc_gotent;
 };
 
 #define elf64_x86_64_tdata(abfd) \
@@ -373,6 +420,8 @@ struct elf64_x86_64_obj_tdata
 #define elf64_x86_64_local_got_tls_type(abfd) \
   (elf64_x86_64_tdata (abfd)->local_got_tls_type)
 
+#define elf64_x86_64_local_tlsdesc_gotent(abfd) \
+  (elf64_x86_64_tdata (abfd)->local_tlsdesc_gotent)
 
 /* x86-64 ELF linker hash table.  */
 
@@ -389,11 +438,23 @@ struct elf64_x86_64_link_hash_table
   asection *sdynbss;
   asection *srelbss;
 
+  /* The offset into splt of the PLT entry for the TLS descriptor
+     resolver.  Special values are 0, if not necessary (or not found
+     to be necessary yet), and -1 if needed but not determined
+     yet.  */
+  bfd_vma tlsdesc_plt;
+  /* The offset into sgot of the GOT entry used by the PLT entry
+     above.  */
+  bfd_vma tlsdesc_got;
+
   union {
     bfd_signed_vma refcount;
     bfd_vma offset;
   } tls_ld_got;
 
+  /* The amount of space used by the jump slots in the GOT.  */
+  bfd_vma sgotplt_jump_table_size;
+
   /* Small local sym to section mapping cache.  */
   struct sym_sec_cache sym_sec;
 };
@@ -403,6 +464,9 @@ struct elf64_x86_64_link_hash_table
 #define elf64_x86_64_hash_table(p) \
   ((struct elf64_x86_64_link_hash_table *) ((p)->hash))
 
+#define elf64_x86_64_compute_jump_table_size(htab) \
+  ((htab)->srelplt->reloc_count * GOT_ENTRY_SIZE)
+
 /* Create an entry in an x86-64 ELF linker hash table.	*/
 
 static struct bfd_hash_entry *
@@ -428,6 +492,7 @@ link_hash_newfunc (struct bfd_hash_entry
       eh = (struct elf64_x86_64_link_hash_entry *) entry;
       eh->dyn_relocs = NULL;
       eh->tls_type = GOT_UNKNOWN;
+      eh->tlsdesc_got = (bfd_vma) -1;
     }
 
   return entry;
@@ -459,7 +524,10 @@ elf64_x86_64_link_hash_table_create (bfd
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
   ret->sym_sec.abfd = NULL;
+  ret->tlsdesc_plt = 0;
+  ret->tlsdesc_got = 0;
   ret->tls_ld_got.refcount = 0;
+  ret->sgotplt_jump_table_size = 0;
 
   return &ret->elf.root;
 }
@@ -619,6 +687,8 @@ elf64_x86_64_tls_transition (struct bfd_
   switch (r_type)
     {
     case R_X86_64_TLSGD:
+    case R_X86_64_GOTPC32_TLSDESC:
+    case R_X86_64_TLSDESC_CALL:
     case R_X86_64_GOTTPOFF:
       if (is_local)
 	return R_X86_64_TPOFF32;
@@ -709,6 +779,8 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 	case R_X86_64_GOT32:
 	case R_X86_64_GOTPCREL:
 	case R_X86_64_TLSGD:
+	case R_X86_64_GOTPC32_TLSDESC:
+	case R_X86_64_TLSDESC_CALL:
 	  /* This symbol requires a global offset table entry.	*/
 	  {
 	    int tls_type, old_tls_type;
@@ -718,6 +790,9 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 	      default: tls_type = GOT_NORMAL; break;
 	      case R_X86_64_TLSGD: tls_type = GOT_TLS_GD; break;
 	      case R_X86_64_GOTTPOFF: tls_type = GOT_TLS_IE; break;
+	      case R_X86_64_GOTPC32_TLSDESC:
+	      case R_X86_64_TLSDESC_CALL:
+		tls_type = GOT_TLS_GDESC; break;
 	      }
 
 	    if (h != NULL)
@@ -736,14 +811,17 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 		    bfd_size_type size;
 
 		    size = symtab_hdr->sh_info;
-		    size *= sizeof (bfd_signed_vma) + sizeof (char);
+		    size *= sizeof (bfd_signed_vma)
+		      + sizeof (bfd_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;
+		    elf64_x86_64_local_tlsdesc_gotent (abfd)
+		      = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info);
 		    elf64_x86_64_local_got_tls_type (abfd)
-		      = (char *) (local_got_refcounts + symtab_hdr->sh_info);
+		      = (char *) (local_got_refcounts + 2 * symtab_hdr->sh_info);
 		  }
 		local_got_refcounts[r_symndx] += 1;
 		old_tls_type
@@ -753,10 +831,14 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 	    /* 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))
+		&& (! GOT_TLS_GD_ANY_P (old_tls_type)
+		    || tls_type != GOT_TLS_IE))
 	      {
-		if (old_tls_type == GOT_TLS_IE && tls_type == GOT_TLS_GD)
+		if (old_tls_type == GOT_TLS_IE && GOT_TLS_GD_ANY_P (tls_type))
 		  tls_type = old_tls_type;
+		else if (GOT_TLS_GD_ANY_P (old_tls_type)
+			 && GOT_TLS_GD_ANY_P (tls_type))
+		  tls_type |= old_tls_type;
 		else
 		  {
 		    (*_bfd_error_handler)
@@ -1104,6 +1186,8 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, s
 	  break;
 
 	case R_X86_64_TLSGD:
+	case R_X86_64_GOTPC32_TLSDESC:
+	case R_X86_64_TLSDESC_CALL:
 	case R_X86_64_GOTTPOFF:
 	case R_X86_64_GOT32:
 	case R_X86_64_GOTPCREL:
@@ -1371,6 +1455,7 @@ allocate_dynrelocs (struct elf_link_hash
 
 	  /* We also need to make an entry in the .rela.plt section.  */
 	  htab->srelplt->size += sizeof (Elf64_External_Rela);
+	  htab->srelplt->reloc_count++;
 	}
       else
 	{
@@ -1384,6 +1469,9 @@ allocate_dynrelocs (struct elf_link_hash
       h->needs_plt = 0;
     }
 
+  eh = (struct elf64_x86_64_link_hash_entry *) h;
+  eh->tlsdesc_got = (bfd_vma) -1;
+  
   /* If R_X86_64_GOTTPOFF symbol is now local to the binary,
      make it a R_X86_64_TPOFF32 requiring no GOT entry.  */
   if (h->got.refcount > 0
@@ -1406,31 +1494,46 @@ allocate_dynrelocs (struct elf_link_hash
 	    return FALSE;
 	}
 
-      s = htab->sgot;
-      h->got.offset = s->size;
-      s->size += GOT_ENTRY_SIZE;
-      /* R_X86_64_TLSGD needs 2 consecutive GOT slots.  */
-      if (tls_type == GOT_TLS_GD)
-	s->size += GOT_ENTRY_SIZE;
+      if (GOT_TLS_GDESC_P (tls_type))
+	{
+	  eh->tlsdesc_got = htab->sgotplt->size
+	    - elf64_x86_64_compute_jump_table_size (htab);
+	  htab->sgotplt->size += 2 * GOT_ENTRY_SIZE;
+	  h->got.offset = (bfd_vma) -2;
+	}
+      if (! GOT_TLS_GDESC_P (tls_type)
+	  || GOT_TLS_GD_P (tls_type))
+	{
+	  s = htab->sgot;
+	  h->got.offset = s->size;
+	  s->size += GOT_ENTRY_SIZE;
+	  if (GOT_TLS_GD_P (tls_type))
+	    s->size += GOT_ENTRY_SIZE;
+	}
       dyn = htab->elf.dynamic_sections_created;
       /* R_X86_64_TLSGD needs one dynamic relocation if local symbol
 	 and two if global.
 	 R_X86_64_GOTTPOFF needs one dynamic relocation.  */
-      if ((tls_type == GOT_TLS_GD && h->dynindx == -1)
+      if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1)
 	  || tls_type == GOT_TLS_IE)
 	htab->srelgot->size += sizeof (Elf64_External_Rela);
-      else if (tls_type == GOT_TLS_GD)
+      else if (GOT_TLS_GD_P (tls_type))
 	htab->srelgot->size += 2 * sizeof (Elf64_External_Rela);
-      else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-		|| h->root.type != bfd_link_hash_undefweak)
+      else if (! GOT_TLS_GDESC_P (tls_type)
+	       && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+		   || h->root.type != bfd_link_hash_undefweak)
 	       && (info->shared
 		   || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
 	htab->srelgot->size += sizeof (Elf64_External_Rela);
+      if (GOT_TLS_GDESC_P (tls_type))
+	{
+	  htab->srelplt->size += sizeof (Elf64_External_Rela);
+	  htab->tlsdesc_plt = (bfd_vma) -1;
+	}
     }
   else
     h->got.offset = (bfd_vma) -1;
 
-  eh = (struct elf64_x86_64_link_hash_entry *) h;
   if (eh->dyn_relocs == NULL)
     return TRUE;
 
@@ -1578,6 +1681,7 @@ elf64_x86_64_size_dynamic_sections (bfd 
       bfd_signed_vma *local_got;
       bfd_signed_vma *end_local_got;
       char *local_tls_type;
+      bfd_vma *local_tlsdesc_gotent;
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
       asection *srel;
@@ -1621,20 +1725,43 @@ elf64_x86_64_size_dynamic_sections (bfd 
       locsymcount = symtab_hdr->sh_info;
       end_local_got = local_got + locsymcount;
       local_tls_type = elf64_x86_64_local_got_tls_type (ibfd);
+      local_tlsdesc_gotent = elf64_x86_64_local_tlsdesc_gotent (ibfd);
       s = htab->sgot;
       srel = htab->srelgot;
-      for (; local_got < end_local_got; ++local_got, ++local_tls_type)
+      for (; local_got < end_local_got;
+	   ++local_got, ++local_tls_type, ++local_tlsdesc_gotent)
 	{
+	  *local_tlsdesc_gotent = (bfd_vma) -1;
 	  if (*local_got > 0)
 	    {
-	      *local_got = s->size;
-	      s->size += GOT_ENTRY_SIZE;
-	      if (*local_tls_type == GOT_TLS_GD)
-		s->size += GOT_ENTRY_SIZE;
+	      if (GOT_TLS_GDESC_P (*local_tls_type))
+		{
+		  *local_tlsdesc_gotent = htab->sgotplt->size
+		    - elf64_x86_64_compute_jump_table_size (htab);
+		  htab->sgotplt->size += 2 * GOT_ENTRY_SIZE;
+		  *local_got = (bfd_vma) -2;
+		}
+	      if (! GOT_TLS_GDESC_P (*local_tls_type)
+		  || GOT_TLS_GD_P (*local_tls_type))
+		{
+		  *local_got = s->size;
+		  s->size += GOT_ENTRY_SIZE;
+		  if (GOT_TLS_GD_P (*local_tls_type))
+		    s->size += GOT_ENTRY_SIZE;
+		}
 	      if (info->shared
-		  || *local_tls_type == GOT_TLS_GD
+		  || GOT_TLS_GD_ANY_P (*local_tls_type)
 		  || *local_tls_type == GOT_TLS_IE)
-		srel->size += sizeof (Elf64_External_Rela);
+		{
+		  if (GOT_TLS_GDESC_P (*local_tls_type))
+		    {
+		      htab->srelplt->size += sizeof (Elf64_External_Rela);
+		      htab->tlsdesc_plt = (bfd_vma) -1;
+		    }
+		  if (! GOT_TLS_GDESC_P (*local_tls_type)
+		      || GOT_TLS_GD_P (*local_tls_type))
+		    srel->size += sizeof (Elf64_External_Rela);
+		}
 	    }
 	  else
 	    *local_got = (bfd_vma) -1;
@@ -1656,6 +1783,34 @@ elf64_x86_64_size_dynamic_sections (bfd 
      sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
 
+  /* For every jump slot reserved in the sgotplt, reloc_count is
+     incremented.  However, when we reserve space for TLS descriptors,
+     it's not incremented, so in order to compute the space reserved
+     for them, it suffices to multiply the reloc count by the jump
+     slot size.  */
+  if (htab->srelplt)
+    htab->sgotplt_jump_table_size
+      = elf64_x86_64_compute_jump_table_size (htab);
+
+  if (htab->tlsdesc_plt)
+    {
+      /* If we're not using lazy TLS relocations, don't generate the
+	 PLT and GOT entries they require.  */
+      if ((info->flags & DF_BIND_NOW))
+	htab->tlsdesc_plt = 0;
+      else
+	{
+	  htab->tlsdesc_got = htab->sgot->size;
+	  htab->sgot->size += GOT_ENTRY_SIZE;
+	  /* Reserve room for the initial entry.
+	     FIXME: we could probably do away with it in this case.  */
+	  if (htab->splt->size == 0)
+	    htab->splt->size += PLT_ENTRY_SIZE;
+	  htab->tlsdesc_plt = htab->splt->size;
+	  htab->splt->size += PLT_ENTRY_SIZE;
+	}
+    }
+
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
   relocs = FALSE;
@@ -1679,7 +1834,8 @@ elf64_x86_64_size_dynamic_sections (bfd 
 
 	  /* We use the reloc_count field as a counter if we need
 	     to copy relocs into the output file.  */
-	  s->reloc_count = 0;
+	  if (s != htab->srelplt)
+	    s->reloc_count = 0;
 	}
       else
 	{
@@ -1739,6 +1895,11 @@ elf64_x86_64_size_dynamic_sections (bfd 
 	      || !add_dynamic_entry (DT_PLTREL, DT_RELA)
 	      || !add_dynamic_entry (DT_JMPREL, 0))
 	    return FALSE;
+
+	  if (htab->tlsdesc_plt
+	      && (!add_dynamic_entry (DT_TLSDESC_PLT, 0)
+		  || !add_dynamic_entry (DT_TLSDESC_GOT, 0)))
+	    return FALSE;
 	}
 
       if (relocs)
@@ -1766,6 +1927,41 @@ elf64_x86_64_size_dynamic_sections (bfd 
   return TRUE;
 }
 
+static bfd_boolean
+elf64_x86_64_always_size_sections (bfd *output_bfd,
+				   struct bfd_link_info *info)
+{
+  asection *tls_sec = elf_hash_table (info)->tls_sec;
+
+  if (tls_sec)
+    {
+      struct elf_link_hash_entry *tlsbase;
+
+      tlsbase = elf_link_hash_lookup (elf_hash_table (info),
+				      "_TLS_MODULE_BASE_",
+				      FALSE, FALSE, FALSE);
+
+      if (tlsbase && tlsbase->type == STT_TLS)
+	{
+	  struct bfd_link_hash_entry *bh = NULL;
+	  const struct elf_backend_data *bed
+	    = get_elf_backend_data (output_bfd);
+
+	  if (!(_bfd_generic_link_add_one_symbol
+		(info, output_bfd, "_TLS_MODULE_BASE_", BSF_LOCAL,
+		 tls_sec, 0, NULL, FALSE,
+		 bed->collect, &bh)))
+	    return FALSE;
+	  tlsbase = (struct elf_link_hash_entry *)bh;
+	  tlsbase->def_regular = 1;
+	  tlsbase->other = STV_HIDDEN;
+	  (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE);
+	}
+    }
+
+  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.  */
@@ -1824,6 +2020,7 @@ elf64_x86_64_relocate_section (bfd *outp
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
   bfd_vma *local_got_offsets;
+  bfd_vma *local_tlsdesc_gotents;
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
 
@@ -1834,6 +2031,7 @@ elf64_x86_64_relocate_section (bfd *outp
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (input_bfd);
   local_got_offsets = elf_local_got_offsets (input_bfd);
+  local_tlsdesc_gotents = elf64_x86_64_local_tlsdesc_gotent (input_bfd);
 
   rel = relocs;
   relend = relocs + input_section->reloc_count;
@@ -1845,7 +2043,7 @@ elf64_x86_64_relocate_section (bfd *outp
       struct elf_link_hash_entry *h;
       Elf_Internal_Sym *sym;
       asection *sec;
-      bfd_vma off;
+      bfd_vma off, offplt;
       bfd_vma relocation;
       bfd_boolean unresolved_reloc;
       bfd_reloc_status_type r;
@@ -2204,6 +2402,8 @@ elf64_x86_64_relocate_section (bfd *outp
 	  break;
 
 	case R_X86_64_TLSGD:
+	case R_X86_64_GOTPC32_TLSDESC:
+	case R_X86_64_TLSDESC_CALL:
 	case R_X86_64_GOTTPOFF:
 	  r_type = elf64_x86_64_tls_transition (info, r_type, h == NULL);
 	  tls_type = GOT_UNKNOWN;
@@ -2215,7 +2415,9 @@ elf64_x86_64_relocate_section (bfd *outp
 	      if (!info->shared && h->dynindx == -1 && tls_type == GOT_TLS_IE)
 		r_type = R_X86_64_TPOFF32;
 	    }
-	  if (r_type == R_X86_64_TLSGD)
+	  if (r_type == R_X86_64_TLSGD
+	      || r_type == R_X86_64_GOTPC32_TLSDESC
+	      || r_type == R_X86_64_TLSDESC_CALL)
 	    {
 	      if (tls_type == GOT_TLS_IE)
 		r_type = R_X86_64_GOTTPOFF;
@@ -2257,6 +2459,67 @@ elf64_x86_64_relocate_section (bfd *outp
 		  rel++;
 		  continue;
 		}
+	      else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC)
+		{
+		  /* GDesc -> LE transition.
+		     It's originally something like:
+		     leaq x@tlsdesc(%rip), %rax
+
+		     Change it to:
+		     movl $x@tpoff, %rax
+		     
+		     Registers other than %rax may be set up here.  */
+		  
+		  unsigned int val, type, type2;
+		  bfd_vma roff;
+
+		  /* First, make sure it's a leaq adding rip to a
+		     32-bit offset into any register, although it's
+		     probably almost always going to be rax.  */
+		  roff = rel->r_offset;
+		  BFD_ASSERT (roff >= 3);
+		  type = bfd_get_8 (input_bfd, contents + roff - 3);
+		  BFD_ASSERT ((type & 0xfb) == 0x48);
+		  type2 = bfd_get_8 (input_bfd, contents + roff - 2);
+		  BFD_ASSERT (type2 == 0x8d);
+		  val = bfd_get_8 (input_bfd, contents + roff - 1);
+		  BFD_ASSERT ((val & 0xc7) == 0x05);
+		  BFD_ASSERT (roff + 4 <= input_section->size);
+
+		  /* Now modify the instruction as appropriate.  */
+		  bfd_put_8 (output_bfd, 0x48 | ((type >> 2) & 1),
+			     contents + roff - 3);
+		  bfd_put_8 (output_bfd, 0xc7, contents + roff - 2);
+		  bfd_put_8 (output_bfd, 0xc0 | ((val >> 3) & 7),
+			     contents + roff - 1);
+		  bfd_put_32 (output_bfd, tpoff (info, relocation),
+			      contents + roff);
+		  continue;
+		}
+	      else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSDESC_CALL)
+		{
+		  /* GDesc -> LE transition.
+		     It's originally:
+		     call *(%rax)
+		     Turn it into:
+		     rex64 nop.  */
+		  
+		  unsigned int val, type;
+		  bfd_vma roff;
+
+		  /* First, make sure it's a call *(%rax).  */
+		  roff = rel->r_offset;
+		  BFD_ASSERT (roff + 2 <= input_section->size);
+		  type = bfd_get_8 (input_bfd, contents + roff);
+		  BFD_ASSERT (type == 0xff);
+		  val = bfd_get_8 (input_bfd, contents + roff + 1);
+		  BFD_ASSERT (val == 0x10);
+
+		  /* Now modify the instruction as appropriate.  */
+		  bfd_put_8 (output_bfd, 0x48, contents + roff);
+		  bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
+		  continue;
+		}
 	      else
 		{
 		  unsigned int val, type, reg;
@@ -2322,13 +2585,17 @@ elf64_x86_64_relocate_section (bfd *outp
 	    abort ();
 
 	  if (h != NULL)
-	    off = h->got.offset;
+	    {
+	      off = h->got.offset;
+	      offplt = elf64_x86_64_hash_entry (h)->tlsdesc_got;
+	    }
 	  else
 	    {
 	      if (local_got_offsets == NULL)
 		abort ();
 
 	      off = local_got_offsets[r_symndx];
+	      offplt = local_tlsdesc_gotents[r_symndx];
 	    }
 
 	  if ((off & 1) != 0)
@@ -2338,30 +2605,61 @@ elf64_x86_64_relocate_section (bfd *outp
 	      Elf_Internal_Rela outrel;
 	      bfd_byte *loc;
 	      int dr_type, indx;
+	      asection *sreloc;
 
 	      if (htab->srelgot == NULL)
 		abort ();
 
+	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
+
+	      if (GOT_TLS_GDESC_P (tls_type))
+		{
+		  outrel.r_info = ELF64_R_INFO (indx, R_X86_64_TLSDESC);
+		  BFD_ASSERT (htab->sgotplt_jump_table_size + offplt
+			      + 2 * GOT_ENTRY_SIZE <= htab->sgotplt->size);
+		  outrel.r_offset = (htab->sgotplt->output_section->vma
+				     + htab->sgotplt->output_offset
+				     + offplt
+				     + htab->sgotplt_jump_table_size);
+		  sreloc = htab->srelplt;
+		  loc = sreloc->contents;
+		  loc += sreloc->reloc_count++
+		    * sizeof (Elf64_External_Rela);
+		  BFD_ASSERT (loc + sizeof (Elf64_External_Rela)
+			      <= sreloc->contents + sreloc->size);
+		  if (indx == 0)
+		    outrel.r_addend = relocation - dtpoff_base (info);
+		  else
+		    outrel.r_addend = 0;
+		  bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+		}
+
+	      sreloc = htab->srelgot;
+
 	      outrel.r_offset = (htab->sgot->output_section->vma
 				 + htab->sgot->output_offset + off);
 
-	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
-	      if (r_type == R_X86_64_TLSGD)
+	      if (GOT_TLS_GD_P (tls_type))
 		dr_type = R_X86_64_DTPMOD64;
+	      else if (GOT_TLS_GDESC_P (tls_type))
+		goto dr_done;
 	      else
 		dr_type = R_X86_64_TPOFF64;
 
 	      bfd_put_64 (output_bfd, 0, htab->sgot->contents + off);
 	      outrel.r_addend = 0;
-	      if (dr_type == R_X86_64_TPOFF64 && indx == 0)
+	      if ((dr_type == R_X86_64_TPOFF64
+		   || dr_type == R_X86_64_TLSDESC) && indx == 0)
 		outrel.r_addend = relocation - dtpoff_base (info);
 	      outrel.r_info = ELF64_R_INFO (indx, dr_type);
 
-	      loc = htab->srelgot->contents;
-	      loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela);
+	      loc = sreloc->contents;
+	      loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela);
+	      BFD_ASSERT (loc + sizeof (Elf64_External_Rela)
+			  <= sreloc->contents + sreloc->size);
 	      bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
 
-	      if (r_type == R_X86_64_TLSGD)
+	      if (GOT_TLS_GD_P (tls_type))
 		{
 		  if (indx == 0)
 		    {
@@ -2377,27 +2675,37 @@ elf64_x86_64_relocate_section (bfd *outp
 		      outrel.r_info = ELF64_R_INFO (indx,
 						    R_X86_64_DTPOFF64);
 		      outrel.r_offset += GOT_ENTRY_SIZE;
-		      htab->srelgot->reloc_count++;
+		      sreloc->reloc_count++;
 		      loc += sizeof (Elf64_External_Rela);
+		      BFD_ASSERT (loc + sizeof (Elf64_External_Rela)
+				  <= sreloc->contents + sreloc->size);
 		      bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
 		    }
 		}
 
+	    dr_done:
 	      if (h != NULL)
 		h->got.offset |= 1;
 	      else
 		local_got_offsets[r_symndx] |= 1;
 	    }
 
-	  if (off >= (bfd_vma) -2)
+	  if (off >= (bfd_vma) -2
+	      && ! GOT_TLS_GDESC_P (tls_type))
 	    abort ();
 	  if (r_type == ELF64_R_TYPE (rel->r_info))
 	    {
-	      relocation = htab->sgot->output_section->vma
-			   + htab->sgot->output_offset + off;
+	      if (r_type == R_X86_64_GOTPC32_TLSDESC
+		  || r_type == R_X86_64_TLSDESC_CALL)
+		relocation = htab->sgotplt->output_section->vma
+		  + htab->sgotplt->output_offset
+		  + offplt + htab->sgotplt_jump_table_size;
+	      else
+		relocation = htab->sgot->output_section->vma
+		  + htab->sgot->output_offset + off;
 	      unresolved_reloc = FALSE;
 	    }
-	  else
+	  else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSGD)
 	    {
 	      unsigned int i;
 	      static unsigned char tlsgd[8]
@@ -2437,6 +2745,79 @@ elf64_x86_64_relocate_section (bfd *outp
 	      rel++;
 	      continue;
 	    }
+	  else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC)
+	    {
+	      /* GDesc -> IE transition.
+		 It's originally something like:
+		 leaq x@tlsdesc(%rip), %rax
+
+		 Change it to:
+		 movq x@gottpoff(%rip), %rax # before rex64 nop
+		     
+		 Registers other than %rax may be set up here.  */
+		  
+	      unsigned int val, type, type2;
+	      bfd_vma roff;
+
+	      /* First, make sure it's a leaq adding rip to a 32-bit
+		 offset into any register, although it's probably
+		 almost always going to be rax.  */
+	      roff = rel->r_offset;
+	      BFD_ASSERT (roff >= 3);
+	      type = bfd_get_8 (input_bfd, contents + roff - 3);
+	      BFD_ASSERT ((type & 0xfb) == 0x48);
+	      type2 = bfd_get_8 (input_bfd, contents + roff - 2);
+	      BFD_ASSERT (type2 == 0x8d);
+	      val = bfd_get_8 (input_bfd, contents + roff - 1);
+	      BFD_ASSERT ((val & 0xc7) == 0x05);
+	      BFD_ASSERT (roff + 4 <= input_section->size);
+
+	      /* Now modify the instruction as appropriate.  */
+	      /* To turn a leaq into a movq in the form we use it, it
+		 suffices to change the second byte from 0x8d to 0x8b.
+		 aoliva FIXME: should we decide to keep the leaq, all
+		 we have to do is remove the statement below, and
+		 adjust the relaxation of R_X86_64_TLSDESC_CALL.  */
+	      bfd_put_8 (output_bfd, 0x8b, contents + roff - 2);
+
+	      bfd_put_32 (output_bfd,
+			  htab->sgot->output_section->vma
+			  + htab->sgot->output_offset + off
+			  - rel->r_offset
+			  - input_section->output_section->vma
+			  - input_section->output_offset
+			  - 4,
+			  contents + roff);
+	      continue;
+	    }
+	  else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSDESC_CALL)
+	    {
+	      /* GDesc -> IE transition.
+		 It's originally:
+		 call *(%rax)
+
+		 Change it to:
+		 rex64 nop.  */
+		  
+	      unsigned int val, type;
+	      bfd_vma roff;
+
+	      /* First, make sure it's a call *(%eax).  */
+	      roff = rel->r_offset;
+	      BFD_ASSERT (roff + 2 <= input_section->size);
+	      type = bfd_get_8 (input_bfd, contents + roff);
+	      BFD_ASSERT (type == 0xff);
+	      val = bfd_get_8 (input_bfd, contents + roff + 1);
+	      BFD_ASSERT (val == 0x10);
+
+	      /* Now modify the instruction as appropriate.  */
+	      bfd_put_8 (output_bfd, 0x48, contents + roff);
+	      bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
+
+	      continue;
+	    }
+	  else
+	    BFD_ASSERT (FALSE);
 	  break;
 
 	case R_X86_64_TLSLD:
@@ -2675,7 +3056,7 @@ elf64_x86_64_finish_dynamic_symbol (bfd 
     }
 
   if (h->got.offset != (bfd_vma) -1
-      && elf64_x86_64_hash_entry (h)->tls_type != GOT_TLS_GD
+      && ! GOT_TLS_GD_ANY_P (elf64_x86_64_hash_entry (h)->tls_type)
       && elf64_x86_64_hash_entry (h)->tls_type != GOT_TLS_IE)
     {
       Elf_Internal_Rela rela;
@@ -2830,6 +3211,18 @@ elf64_x86_64_finish_dynamic_sections (bf
 		  dyn.d_un.d_val -= s->size;
 		}
 	      break;
+
+	    case DT_TLSDESC_PLT:
+	      s = htab->splt;
+	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
+		+ htab->tlsdesc_plt;
+	      break;
+	      
+	    case DT_TLSDESC_GOT:
+	      s = htab->sgot;
+	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
+		+ htab->tlsdesc_got;
+	      break;
 	    }
 
 	  bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
@@ -2864,6 +3257,40 @@ elf64_x86_64_finish_dynamic_sections (bf
 
 	  elf_section_data (htab->splt->output_section)->this_hdr.sh_entsize =
 	    PLT_ENTRY_SIZE;
+
+	  if (htab->tlsdesc_plt)
+	    {
+	      bfd_put_64 (output_bfd, (bfd_vma) 0,
+			  htab->sgot->contents + htab->tlsdesc_got);
+
+	      memcpy (htab->splt->contents + htab->tlsdesc_plt,
+		      elf64_x86_64_plt0_entry,
+		      PLT_ENTRY_SIZE);
+
+	      /* Add offset for pushq GOT+8(%rip), since the
+		 instruction uses 6 bytes subtract this value.  */
+	      bfd_put_32 (output_bfd,
+			  (htab->sgotplt->output_section->vma
+			   + htab->sgotplt->output_offset
+			   + 8
+			   - htab->splt->output_section->vma
+			   - htab->splt->output_offset
+			   - htab->tlsdesc_plt
+			   - 6),
+			  htab->splt->contents + htab->tlsdesc_plt + 2);
+	      /* Add offset for jmp *GOT+TDG(%rip), where TGD stands for
+		 htab->tlsdesc_got. The 12 is the offset to the end of
+		 the instruction.  */
+	      bfd_put_32 (output_bfd,
+			  (htab->sgot->output_section->vma
+			   + htab->sgot->output_offset
+			   + htab->tlsdesc_got
+			   - htab->splt->output_section->vma
+			   - htab->splt->output_offset
+			   - htab->tlsdesc_plt
+			   - 12),
+			  htab->splt->contents + htab->tlsdesc_plt + 8);
+	    }
 	}
     }
 
@@ -3135,6 +3562,7 @@ static const struct bfd_elf_special_sect
 #define elf_backend_reloc_type_class	    elf64_x86_64_reloc_type_class
 #define elf_backend_relocate_section	    elf64_x86_64_relocate_section
 #define elf_backend_size_dynamic_sections   elf64_x86_64_size_dynamic_sections
+#define elf_backend_always_size_sections    elf64_x86_64_always_size_sections
 #define elf_backend_plt_sym_val		    elf64_x86_64_plt_sym_val
 #define elf_backend_object_p		    elf64_x86_64_elf_object_p
 #define bfd_elf64_mkobject		    elf64_x86_64_mkobject
Index: bfd/libbfd.h
===================================================================
RCS file: /cvs/uberbaum/./bfd/libbfd.h,v
retrieving revision 1.157
diff -u -p -r1.157 libbfd.h
--- bfd/libbfd.h 8 Sep 2005 12:49:18 -0000 1.157
+++ bfd/libbfd.h 21 Sep 2005 06:12:13 -0000
@@ -1044,6 +1044,9 @@ static const char *const bfd_reloc_code_
   "BFD_RELOC_386_TLS_DTPMOD32",
   "BFD_RELOC_386_TLS_DTPOFF32",
   "BFD_RELOC_386_TLS_TPOFF32",
+  "BFD_RELOC_386_TLS_GOTDESC",
+  "BFD_RELOC_386_TLS_DESC_CALL",
+  "BFD_RELOC_386_TLS_DESC",
   "BFD_RELOC_X86_64_GOT32",
   "BFD_RELOC_X86_64_PLT32",
   "BFD_RELOC_X86_64_COPY",
@@ -1062,6 +1065,9 @@ static const char *const bfd_reloc_code_
   "BFD_RELOC_X86_64_TPOFF32",
   "BFD_RELOC_X86_64_GOTOFF64",
   "BFD_RELOC_X86_64_GOTPC32",
+  "BFD_RELOC_X86_64_GOTPC32_TLSDESC",
+  "BFD_RELOC_X86_64_TLSDESC_CALL",
+  "BFD_RELOC_X86_64_TLSDESC",
   "BFD_RELOC_NS32K_IMM_8",
   "BFD_RELOC_NS32K_IMM_16",
   "BFD_RELOC_NS32K_IMM_32",
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/uberbaum/./bfd/reloc.c,v
retrieving revision 1.138
diff -u -p -r1.138 reloc.c
--- bfd/reloc.c 8 Sep 2005 12:49:19 -0000 1.138
+++ bfd/reloc.c 21 Sep 2005 06:12:15 -0000
@@ -2329,6 +2329,12 @@ ENUMX
   BFD_RELOC_386_TLS_DTPOFF32
 ENUMX
   BFD_RELOC_386_TLS_TPOFF32
+ENUMX
+  BFD_RELOC_386_TLS_GOTDESC
+ENUMX
+  BFD_RELOC_386_TLS_DESC_CALL
+ENUMX
+  BFD_RELOC_386_TLS_DESC
 ENUMDOC
   i386/elf relocations
 
@@ -2368,6 +2374,12 @@ ENUMX
   BFD_RELOC_X86_64_GOTOFF64
 ENUMX
   BFD_RELOC_X86_64_GOTPC32
+ENUMX
+  BFD_RELOC_X86_64_GOTPC32_TLSDESC
+ENUMX
+  BFD_RELOC_X86_64_TLSDESC_CALL
+ENUMX
+  BFD_RELOC_X86_64_TLSDESC
 ENUMDOC
   x86-64/elf relocations
 
Index: binutils/readelf.c
===================================================================
RCS file: /cvs/uberbaum/./binutils/readelf.c,v
retrieving revision 1.316
diff -u -p -r1.316 readelf.c
--- binutils/readelf.c 20 Sep 2005 17:55:13 -0000 1.316
+++ binutils/readelf.c 21 Sep 2005 06:12:22 -0000
@@ -1632,6 +1632,8 @@ get_dynamic_type (unsigned long type)
 
     case DT_VERSYM:	return "VERSYM";
 
+    case DT_TLSDESC_GOT: return "TLSDESC_GOT";
+    case DT_TLSDESC_PLT: return "TLSDESC_PLT";
     case DT_RELACOUNT:	return "RELACOUNT";
     case DT_RELCOUNT:	return "RELCOUNT";
     case DT_FLAGS_1:	return "FLAGS_1";
Index: gas/config/tc-i386.c
===================================================================
RCS file: /cvs/uberbaum/./gas/config/tc-i386.c,v
retrieving revision 1.197
diff -u -p -r1.197 tc-i386.c
--- gas/config/tc-i386.c 20 Sep 2005 18:24:47 -0000 1.197
+++ gas/config/tc-i386.c 21 Sep 2005 06:12:32 -0000
@@ -1328,6 +1328,8 @@ tc_i386_fix_adjustable (fixP)
       || fixP->fx_r_type == BFD_RELOC_386_TLS_GOTIE
       || 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_386_TLS_GOTDESC
+      || fixP->fx_r_type == BFD_RELOC_386_TLS_DESC_CALL
       || 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
@@ -1339,6 +1341,8 @@ tc_i386_fix_adjustable (fixP)
       || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF32
       || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF64
       || fixP->fx_r_type == BFD_RELOC_X86_64_GOTOFF64
+      || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPC32_TLSDESC
+      || fixP->fx_r_type == BFD_RELOC_X86_64_TLSDESC_CALL
       || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
     return 0;
@@ -2179,7 +2183,14 @@ optimize_disp ()
 		&& fits_in_signed_byte (disp))
 	      i.types[op] |= Disp8;
 	  }
-	else
+	else if (i.reloc[op] == BFD_RELOC_386_TLS_DESC_CALL
+		 || i.reloc[op] == BFD_RELOC_X86_64_TLSDESC_CALL)
+	  {
+	    fix_new_exp (frag_now, frag_more (0) - frag_now->fr_literal, 0,
+			 i.op[op].disps, 0, i.reloc[op]);
+	    i.types[op] &= ~Disp;
+	  }
+ 	else
 	  /* We only support 64bit displacement on constants.  */
 	  i.types[op] &= ~Disp64;
       }
@@ -3125,7 +3136,13 @@ build_modrm_byte ()
 		  if ((i.index_reg->reg_flags & RegRex) != 0)
 		    i.rex |= REX_EXTY;
 		}
-	      i.rm.mode = mode_from_disp_size (i.types[op]);
+
+	      if (i.disp_operands
+		  && (i.reloc[op] == BFD_RELOC_386_TLS_DESC_CALL
+		      || i.reloc[op] == BFD_RELOC_X86_64_TLSDESC_CALL))
+		i.rm.mode = 0;
+	      else
+		i.rm.mode = mode_from_disp_size (i.types[op]);
 	    }
 
 	  if (fake_zero_displacement)
@@ -3798,7 +3815,9 @@ lex_got (enum bfd_reloc_code_real *reloc
     { "DTPOFF",   { BFD_RELOC_386_TLS_LDO_32, BFD_RELOC_X86_64_DTPOFF32 }, Imm32|Imm32S|Imm64|Disp32|Disp64 },
     { "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE,  0                         }, 0 },
     { "INDNTPOFF",{ BFD_RELOC_386_TLS_IE,     0                         }, 0 },
-    { "GOT",      { BFD_RELOC_386_GOT32,      BFD_RELOC_X86_64_GOT32    }, Imm32|Imm32S|Disp32 }
+    { "GOT",      { BFD_RELOC_386_GOT32,      BFD_RELOC_X86_64_GOT32    }, Imm32|Imm32S|Disp32 },
+    { "TLSDESC",  { BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_X86_64_GOTPC32_TLSDESC }, Imm32|Imm32S|Disp32 },
+    { "TLSCALL",  { BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_X86_64_TLSDESC_CALL }, Imm32|Imm32S|Disp32 }
   };
   char *cp;
   unsigned int j;
@@ -5008,9 +5027,11 @@ md_apply_fix (fixP, valP, seg)
       case BFD_RELOC_386_TLS_IE_32:
       case BFD_RELOC_386_TLS_IE:
       case BFD_RELOC_386_TLS_GOTIE:
+      case BFD_RELOC_386_TLS_GOTDESC:
       case BFD_RELOC_X86_64_TLSGD:
       case BFD_RELOC_X86_64_TLSLD:
       case BFD_RELOC_X86_64_GOTTPOFF:
+      case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
 	value = 0; /* Fully resolved at runtime.  No addend.  */
 	/* Fallthrough */
       case BFD_RELOC_386_TLS_LE:
@@ -5023,6 +5044,13 @@ md_apply_fix (fixP, valP, seg)
 	S_SET_THREAD_LOCAL (fixP->fx_addsy);
 	break;
 
+      case BFD_RELOC_386_TLS_DESC_CALL:
+      case BFD_RELOC_X86_64_TLSDESC_CALL:
+	value = 0; /* Fully resolved at runtime.  No addend.  */
+	S_SET_THREAD_LOCAL (fixP->fx_addsy);
+	fixP->fx_done = 0;
+	return;
+
       case BFD_RELOC_386_GOT32:
       case BFD_RELOC_X86_64_GOT32:
 	value = 0; /* Fully resolved at runtime.  No addend.  */
@@ -5501,6 +5529,8 @@ tc_gen_reloc (section, fixp)
     case BFD_RELOC_386_TLS_GOTIE:
     case BFD_RELOC_386_TLS_LE_32:
     case BFD_RELOC_386_TLS_LE:
+    case BFD_RELOC_386_TLS_GOTDESC:
+    case BFD_RELOC_386_TLS_DESC_CALL:
     case BFD_RELOC_X86_64_TLSGD:
     case BFD_RELOC_X86_64_TLSLD:
     case BFD_RELOC_X86_64_DTPOFF32:
@@ -5510,6 +5540,8 @@ tc_gen_reloc (section, fixp)
     case BFD_RELOC_X86_64_TPOFF64:
     case BFD_RELOC_X86_64_GOTOFF64:
     case BFD_RELOC_X86_64_GOTPC32:
+    case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
+    case BFD_RELOC_X86_64_TLSDESC_CALL:
     case BFD_RELOC_RVA:
     case BFD_RELOC_VTABLE_ENTRY:
     case BFD_RELOC_VTABLE_INHERIT:
@@ -5604,6 +5636,8 @@ tc_gen_reloc (section, fixp)
 	  case BFD_RELOC_X86_64_TLSGD:
 	  case BFD_RELOC_X86_64_TLSLD:
 	  case BFD_RELOC_X86_64_GOTTPOFF:
+	  case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
+	  case BFD_RELOC_X86_64_TLSDESC_CALL:
 	    rel->addend = fixp->fx_offset - fixp->fx_size;
 	    break;
 	  default:
Index: include/elf/common.h
===================================================================
RCS file: /cvs/uberbaum/./include/elf/common.h,v
retrieving revision 1.72
diff -u -p -r1.72 common.h
--- include/elf/common.h 14 Jul 2005 22:52:15 -0000 1.72
+++ include/elf/common.h 21 Sep 2005 06:13:15 -0000
@@ -571,6 +571,8 @@
 #define DT_VALRNGHI	0x6ffffdff
 
 #define DT_ADDRRNGLO	0x6ffffe00
+#define DT_TLSDESC_PLT	0x6ffffef6
+#define DT_TLSDESC_GOT	0x6ffffef7
 #define DT_GNU_CONFLICT	0x6ffffef8
 #define DT_GNU_LIBLIST	0x6ffffef9
 #define DT_CONFIG	0x6ffffefa
Index: include/elf/i386.h
===================================================================
RCS file: /cvs/uberbaum/./include/elf/i386.h,v
retrieving revision 1.10
diff -u -p -r1.10 i386.h
--- include/elf/i386.h 10 May 2005 10:21:10 -0000 1.10
+++ include/elf/i386.h 21 Sep 2005 06:13:15 -0000
@@ -1,5 +1,5 @@
 /* ix86 ELF support for BFD.
-   Copyright 1998, 1999, 2000, 2002, 2004 Free Software Foundation, Inc.
+   Copyright 1998, 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -61,6 +61,10 @@ START_RELOC_NUMBERS (elf_i386_reloc_type
      RELOC_NUMBER (R_386_TLS_DTPMOD32, 35)
      RELOC_NUMBER (R_386_TLS_DTPOFF32, 36)
      RELOC_NUMBER (R_386_TLS_TPOFF32,  37)
+/* 38 */
+     RELOC_NUMBER (R_386_TLS_GOTDESC,  39)
+     RELOC_NUMBER (R_386_TLS_DESC_CALL,40)
+     RELOC_NUMBER (R_386_TLS_DESC,     41)
 
      /* Used by Intel.  */
      RELOC_NUMBER (R_386_USED_BY_INTEL_200, 200)
Index: include/elf/x86-64.h
===================================================================
RCS file: /cvs/uberbaum/./include/elf/x86-64.h,v
retrieving revision 1.8
diff -u -p -r1.8 x86-64.h
--- include/elf/x86-64.h 25 Jul 2005 15:41:07 -0000 1.8
+++ include/elf/x86-64.h 21 Sep 2005 06:13:15 -0000
@@ -1,5 +1,5 @@
 /* x86_64 ELF support for BFD.
-   Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
    Contributed by Jan Hubicka <jh@suse.cz>
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -53,6 +53,14 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_ty
      RELOC_NUMBER (R_X86_64_GOTOFF64, 25)     /* 64 bit offset to GOT */
      RELOC_NUMBER (R_X86_64_GOTPC32,  26)     /* 32 bit signed pc relative
                                                  offset to GOT */
+     /* 27 .. 33 */
+     RELOC_NUMBER (R_X86_64_GOTPC32_TLSDESC, 34)
+					      /* 32 bit signed pc relative
+						 offset to TLS descriptor
+						 in the GOT.  */
+     RELOC_NUMBER (R_X86_64_TLSDESC_CALL, 35) /* Relaxable call through TLS
+						 descriptor.  */
+     RELOC_NUMBER (R_X86_64_TLSDESC, 36)      /* 2x64-bit TLS descriptor.  */
      RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250)       /* GNU C++ hack  */
      RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251)         /* GNU C++ hack  */
 END_RELOC_NUMBERS (R_X86_64_max)
Index: ld/testsuite/ld-i386/i386.exp
===================================================================
RCS file: /cvs/uberbaum/./ld/testsuite/ld-i386/i386.exp,v
retrieving revision 1.10
diff -u -p -r1.10 i386.exp
--- ld/testsuite/ld-i386/i386.exp 18 Jul 2005 06:23:40 -0000 1.10
+++ ld/testsuite/ld-i386/i386.exp 21 Sep 2005 06:13:18 -0000
@@ -1,5 +1,5 @@
 # Expect script for ld-i386 tests
-#   Copyright (C) 2002 Free Software Foundation
+#   Copyright (C) 2002, 2005 Free Software Foundation
 #
 # This file is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -22,7 +22,9 @@
 if { !([istarget "i?86-*-elf*"]		
        || ([istarget "i?86-*-linux*"]
 	   && ![istarget "*-*-*aout*"]
-	   && ![istarget "*-*-*oldld*"])) } {
+	   && ![istarget "*-*-*oldld*"])
+       || [istarget "x86_64-*-linux*"]
+       || [istarget "amd64-*-linux*"]) } {
     return
 }
 
@@ -41,6 +43,11 @@ set i386tests {
      {{readelf -Ssrl tlspic.rd} {objdump -drj.text tlspic.dd}
       {objdump -sj.got tlspic.sd} {objdump -sj.tdata tlspic.td}}
       "libtlspic.so"}
+    {"TLS descriptor -fpic -shared transitions" "-shared -melf_i386"
+     "--32" {tlsdesc.s tlspic2.s}
+     {{readelf -Ssrl tlsdesc.rd} {objdump -drj.text tlsdesc.dd}
+      {objdump "-s -j.got -j.got.plt" tlsdesc.sd} {objdump -sj.tdata tlsdesc.td}}
+      "libtlsdesc.so"}
     {"Helper shared library" "-shared -melf_i386"
      "--32" {tlslib.s} {} "libtlslib.so"}
     {"TLS -fpic and -fno-pic exec transitions"
@@ -48,10 +55,19 @@ set i386tests {
      {{readelf -Ssrl tlsbin.rd} {objdump -drj.text tlsbin.dd}
       {objdump -sj.got tlsbin.sd} {objdump -sj.tdata tlsbin.td}}
       "tlsbin"}
+    {"TLS descriptor -fpic and -fno-pic exec transitions"
+     "-melf_i386 tmpdir/libtlslib.so" "--32" {tlsbindesc.s tlsbin.s}
+     {{readelf -Ssrl tlsbindesc.rd} {objdump -drj.text tlsbindesc.dd}
+      {objdump -sj.got tlsbindesc.sd} {objdump -sj.tdata tlsbindesc.td}}
+      "tlsbindesc"}
     {"TLS -fno-pic -shared" "-shared -melf_i386"
      "--32" {tlsnopic1.s tlsnopic2.s}
      {{readelf -Ssrl tlsnopic.rd} {objdump -drj.text tlsnopic.dd}
       {objdump -sj.got tlsnopic.sd}} "libtlsnopic.so"}
+    {"TLS with global dynamic and descriptors"
+	"-shared -melf_i386" "--32" {tlsgdesc.s}
+     {{readelf -Ssrl tlsgdesc.rd} {objdump -drj.text tlsgdesc.dd}}
+      "libtlsgdesc.so"}
     {"TLS in debug sections" "-melf_i386"
      "--32" {tlsg.s}
      {{objdump -sj.debug_foobar tlsg.sd}} "tlsg"}
Index: ld/testsuite/ld-i386/pcrel16.d
===================================================================
RCS file: /cvs/uberbaum/./ld/testsuite/ld-i386/pcrel16.d,v
retrieving revision 1.2
diff -u -p -r1.2 pcrel16.d
--- ld/testsuite/ld-i386/pcrel16.d 3 Aug 2005 16:30:34 -0000 1.2
+++ ld/testsuite/ld-i386/pcrel16.d 21 Sep 2005 06:13:18 -0000
@@ -1,5 +1,6 @@
 #name: PCREL16 overflow
-#ld: -Ttext 0x0
+#as: --32
+#ld: -melf_i386 -Ttext 0x0
 #objdump: -drj.text -m i8086
 
 .*: +file format elf32-i386
Index: ld/testsuite/ld-i386/pcrel8.d
===================================================================
RCS file: /cvs/uberbaum/./ld/testsuite/ld-i386/pcrel8.d,v
retrieving revision 1.1
diff -u -p -r1.1 pcrel8.d
--- ld/testsuite/ld-i386/pcrel8.d 18 Jul 2005 06:23:40 -0000 1.1
+++ ld/testsuite/ld-i386/pcrel8.d 21 Sep 2005 06:13:18 -0000
@@ -1,3 +1,4 @@
 #name: PCREL8 overflow
-#ld:
+#as: --32
+#ld: -melf_i386
 #error: .*relocation truncated to fit: R_386_PC8 .*
Index: ld/testsuite/ld-i386/tlsbindesc.dd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsbindesc.dd
diff -N ld/testsuite/ld-i386/tlsbindesc.dd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsbindesc.dd 21 Sep 2005 06:13:18 -0000
@@ -0,0 +1,461 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --32
+#ld: -melf_i386 tmpdir/libtlslib.so
+#objdump: -drj.text
+#target: i?86-*-*
+
+# PT_TLS layout is:
+# Offset from	Offset from	Name
+# TCB base	TCB end
+# 0x00		-0xa0		sg1..sg8
+# 0x20		-0x80		sl1..sl8
+# 0x40		-0x60		sh1..sh8
+# 0x60		-0x40		bg1..bg8
+# 0x80		-0x20		bl1..bl8
+
+.*: +file format elf32-i386
+
+Disassembly of section .text:
+
+[0-9a-f]+ <fn2>:
+ [0-9a-f]+:	55[ 	]+push   %ebp
+ [0-9a-f]+:	89 e5[ 	]+mov    %esp,%ebp
+ [0-9a-f]+:	53[ 	]+push   %ebx
+ [0-9a-f]+:	50[ 	]+push   %eax
+ [0-9a-f]+:	e8 00 00 00 00[ 	]+call   [0-9a-f]+ <fn2\+0xa>
+ [0-9a-f]+:	5b[ 	]+pop    %ebx
+ [0-9a-f]+:	81 c3 fa 10 00 00[ 	]+add    \$0x10fa,%ebx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable
+ [0-9a-f]+:	8b 83 f8 ff ff ff[ 	]+mov    0xfffffff8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG1
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable where
+#  the variable is referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 e8 ff ff ff[ 	]+mov    0xffffffe8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable where
+#  the variable is referenced through @gotntpoff too
+ [0-9a-f]+:	8b 83 dc ff ff ff[ 	]+mov    0xffffffdc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG3
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable where
+#  the variable is referenced through @gottpoff and @gotntpoff too
+ [0-9a-f]+:	8b 83 f0 ff ff ff[ 	]+mov    0xfffffff0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG4
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with global variable defined in executable
+ [0-9a-f]+:	65[ 	]+gs
+ [0-9a-f]+:	b8 00 f0 ff ff[ 	]+mov    \$0xfffff000,%eax
+#							sg1
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with local variable defined in executable
+ [0-9a-f]+:	65[ 	]+gs
+ [0-9a-f]+:	b8 20 f0 ff ff[ 	]+mov    \$0xfffff020,%eax
+#							sl1
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with hidden variable defined in executable
+ [0-9a-f]+:	65[ 	]+gs
+ [0-9a-f]+:	b8 40 f0 ff ff[ 	]+mov    \$0xfffff040,%eax
+#							sh1
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD -> LE
+ [0-9a-f]+:	65[ 	]+gs
+ [0-9a-f]+:	b8 00 f0 ff ff[ 	]+mov    \$0xfffff000,%eax
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 90 20 f0 ff ff[ 	]+lea    0xfffff020\(%eax\),%edx
+#							sl1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 24 f0 ff ff[ 	]+lea    0xfffff024\(%eax\),%ecx
+#							sl2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD -> LE against hidden variables
+ [0-9a-f]+:	65[ 	]+gs
+ [0-9a-f]+:	b8 00 f0 ff ff[ 	]+mov    \$0xfffff000,%eax
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 90 40 f0 ff ff[ 	]+lea    0xfffff040\(%eax\),%edx
+#							sh1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 44 f0 ff ff[ 	]+lea    0xfffff044\(%eax\),%ecx
+#							sh2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b e8 ff ff ff[ 	]+sub    0xffffffe8\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	sG2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 ec ff ff ff[ 	]+sub    0xffffffec\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b dc ff ff ff[ 	]+add    0xffffffdc\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sG3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 f0 ff ff ff[ 	]+add    0xfffffff0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against global var defined in exec
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 e9 00 10 00 00[ 	]+sub    \$0x1000,%ecx
+#							sg1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE -> LE against local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c0 20 f0 ff ff[ 	]+add    \$0xfffff020,%eax
+#							sl1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against hidden var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 e9 c0 0f 00 00[ 	]+sub    \$0xfc0,%ecx
+#							sh1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  Direct access through %gs
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	8b 8b e0 ff ff ff[ 	]+mov    0xffffffe0\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sG5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 11[ 	]+mov    %gs:\(%ecx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE->LE against local var
+ [0-9a-f]+:	c7 c0 30 f0 ff ff[ 	]+mov    \$0xfffff030,%eax
+#							sl5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 10[ 	]+mov    %gs:\(%eax\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE->LE against hidden var
+ [0-9a-f]+:	c7 c2 50 f0 ff ff[ 	]+mov    \$0xfffff050,%edx
+#							sh5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 12[ 	]+mov    %gs:\(%edx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 5d fc[ 	]+mov    0xfffffffc\(%ebp\),%ebx
+ [0-9a-f]+:	c9[ 	]+leave *
+ [0-9a-f]+:	c3[ 	]+ret *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+
+[0-9a-f]+ <_start>:
+ [0-9a-f]+:	55[ 	]+push   %ebp
+ [0-9a-f]+:	89 e5[ 	]+mov    %esp,%ebp
+ [0-9a-f]+:	e8 00 00 00 00[ 	]+call   [0-9a-f]+ <_start\+0x8>
+ [0-9a-f]+:	59[ 	]+pop    %ecx
+ [0-9a-f]+:	81 c1 a4 0f 00 00[ 	]+add    \$0xfa4,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 91 f4 ff ff ff[ 	]+sub    0xfffffff4\(%ecx\),%edx
+#				->R_386_TLS_TPOFF32	sG6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 05 e8 a0 04 08[ 	]+add    0x804a0e8,%eax
+#				->R_386_TLS_TPOFF	sG7
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff direct %gs access IE against global var
+ [0-9a-f]+:	8b 15 00 a1 04 08[ 	]+mov    0x804a100,%edx
+#				->R_386_TLS_TPOFF	sG8
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 02[ 	]+mov    %gs:\(%edx\),%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against global var defined in exec
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 ea 8c 0f 00 00[ 	]+sub    \$0xf8c,%edx
+#							bg6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff IE -> LE against global var defined in exec
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c0 78 f0 ff ff[ 	]+add    \$0xfffff078,%eax
+#							bg7
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff direct %gs access IE -> LE against global var defined
+#  in exec
+ [0-9a-f]+:	c7 c2 7c f0 ff ff[ 	]+mov    \$0xfffff07c,%edx
+#							bg8
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 02[ 	]+mov    %gs:\(%edx\),%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against local var
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 ea 6c 0f 00 00[ 	]+sub    \$0xf6c,%edx
+#							bl6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff IE -> LE against local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c0 98 f0 ff ff[ 	]+add    \$0xfffff098,%eax
+#							bl7
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff direct %gs access IE -> LE against local var
+ [0-9a-f]+:	c7 c2 9c f0 ff ff[ 	]+mov    \$0xfffff09c,%edx
+#							bl8
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 02[ 	]+mov    %gs:\(%edx\),%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against hidden but not local var
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 ea ac 0f 00 00[ 	]+sub    \$0xfac,%edx
+#							sh6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff IE -> LE against hidden but not local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c0 58 f0 ff ff[ 	]+add    \$0xfffff058,%eax
+#							sh7
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff direct %gs access IE -> LE against hidden but not
+#  local var
+ [0-9a-f]+:	c7 c2 5c f0 ff ff[ 	]+mov    \$0xfffff05c,%edx
+#							sh8
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 02[ 	]+mov    %gs:\(%edx\),%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @tpoff, global var defined in exec
+ [0-9a-f]+:	ba 00 10 00 00[ 	]+mov    \$0x1000,%edx
+#							sg1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	29 d0[ 	]+sub    %edx,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @tpoff, local var
+ [0-9a-f]+:	b8 7f 0f 00 00[ 	]+mov    \$0xf7f,%eax
+#							bl1+1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	29 c2[ 	]+sub    %eax,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @tpoff, hidden var defined in exec
+ [0-9a-f]+:	b8 bd 0f 00 00[ 	]+mov    \$0xfbd,%eax
+#							sh1+3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	29 c2[ 	]+sub    %eax,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, global var defined in exec
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 90 04 f0 ff ff[ 	]+lea    0xfffff004\(%eax\),%edx
+#							sg2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, local var, non-canonical sequence
+ [0-9a-f]+:	b8 86 f0 ff ff[ 	]+mov    \$0xfffff086,%eax
+#							bl2+2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	01 c2[ 	]+add    %eax,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, hidden var defined in exec, non-canonical sequence
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c2 45 f0 ff ff[ 	]+add    \$0xfffff045,%edx
+#							sh2+1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, global var defined in exec
+ [0-9a-f]+:	65 a1 08 f0 ff ff[ 	]+mov    %gs:0xfffff008,%eax
+#							sg3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, local var
+ [0-9a-f]+:	65 8b 15 8b f0 ff ff[ 	]+mov    %gs:0xfffff08b,%edx
+#							bl3+3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, hidden var defined in exec
+ [0-9a-f]+:	65 8b 15 49 f0 ff ff[ 	]+mov    %gs:0xfffff049,%edx
+#							sh3+1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 5d fc[ 	]+mov    0xfffffffc\(%ebp\),%ebx
+ [0-9a-f]+:	c9[ 	]+leave *
+ [0-9a-f]+:	c3[ 	]+ret *
Index: ld/testsuite/ld-i386/tlsbindesc.rd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsbindesc.rd
diff -N ld/testsuite/ld-i386/tlsbindesc.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsbindesc.rd 21 Sep 2005 06:13:18 -0000
@@ -0,0 +1,154 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --32
+#ld: -melf_i386 tmpdir/libtlslib.so
+#readelf: -Ssrl
+#target: i?86-*-*
+
+There are 15 section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+  \[ 1\] \.interp +.*
+  \[ 2\] \.hash +.*
+  \[ 3\] \.dynsym +.*
+  \[ 4\] \.dynstr +.*
+  \[ 5\] \.rel.dyn +.*
+  \[ 6\] \.text +PROGBITS +0+8049000 .*
+  \[ 7\] \.tdata +PROGBITS +0+804a000 [0-9a-f]+ 000060 00 WAT  0   0 4096
+  \[ 8\] \.tbss +NOBITS +[0-9a-f]+ [0-9a-f]+ 000040 00 WAT  0   0  1
+  \[ 9\] \.dynamic +DYNAMIC +0+804a060 .*
+  \[10\] \.got +PROGBITS +0+804a0e0 .*
+  \[11\] \.got\.plt +PROGBITS +0+804a104 .*
+  \[12\] \.shstrtab +.*
+  \[13\] \.symtab +.*
+  \[14\] \.strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x8049158
+There are 6 program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  PHDR.*
+  INTERP.*
+.*Requesting program interpreter.*
+  LOAD.*
+  LOAD.*
+  DYNAMIC.*
+  TLS +0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x0+60 0x0+a0 R +0x1000
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +
+   01 +.interp *
+   02 +.interp .hash .dynsym .dynstr .rel.dyn .text *
+   03 +.tdata .dynamic .got .got.plt *
+   04 +.dynamic *
+   05 +.tdata .tbss *
+
+Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 9 entries:
+ Offset +Info +Type +Sym.Value +Sym. Name
+0+804a0e0  0000010e R_386_TLS_TPOFF +0+ +sG3
+0+804a0e4  0000020e R_386_TLS_TPOFF +0+ +sG5
+0+804a0e8  0000030e R_386_TLS_TPOFF +0+ +sG7
+0+804a0ec  00000425 R_386_TLS_TPOFF32 0+ +sG2
+0+804a0f0  00000525 R_386_TLS_TPOFF32 0+ +sG4
+0+804a0f4  0000050e R_386_TLS_TPOFF +0+ +sG4
+0+804a0f8  00000725 R_386_TLS_TPOFF32 0+ +sG6
+0+804a0fc  00000825 R_386_TLS_TPOFF32 0+ +sG1
+0+804a100  00000b0e R_386_TLS_TPOFF +0+ +sG8
+
+Symbol table '.dynsym' contains 12 entries:
+ +Num: +Value  Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG7
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG8
+
+Symbol table '.symtab' contains 71 entries:
+ +Num: +Value  Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +[0-9]+: 00000020 +0 TLS +LOCAL  DEFAULT +7 sl1
+ +[0-9]+: 00000024 +0 TLS +LOCAL  DEFAULT +7 sl2
+ +[0-9]+: 00000028 +0 TLS +LOCAL  DEFAULT +7 sl3
+ +[0-9]+: 0000002c +0 TLS +LOCAL  DEFAULT +7 sl4
+ +[0-9]+: 00000030 +0 TLS +LOCAL  DEFAULT +7 sl5
+ +[0-9]+: 00000034 +0 TLS +LOCAL  DEFAULT +7 sl6
+ +[0-9]+: 00000038 +0 TLS +LOCAL  DEFAULT +7 sl7
+ +[0-9]+: 0000003c +0 TLS +LOCAL  DEFAULT +7 sl8
+ +[0-9]+: 00000080 +0 TLS +LOCAL  DEFAULT +8 bl1
+ +[0-9]+: 00000084 +0 TLS +LOCAL  DEFAULT +8 bl2
+ +[0-9]+: 00000088 +0 TLS +LOCAL  DEFAULT +8 bl3
+ +[0-9]+: 0000008c +0 TLS +LOCAL  DEFAULT +8 bl4
+ +[0-9]+: 00000090 +0 TLS +LOCAL  DEFAULT +8 bl5
+ +[0-9]+: 00000094 +0 TLS +LOCAL  DEFAULT +8 bl6
+ +[0-9]+: 00000098 +0 TLS +LOCAL  DEFAULT +8 bl7
+ +[0-9]+: 0000009c +0 TLS +LOCAL  DEFAULT +8 bl8
+ +[0-9]+: 00000000 +0 TLS +LOCAL  HIDDEN +7 _TLS_MODULE_BASE_
+ +[0-9]+: 0+804a060 +0 OBJECT  LOCAL  HIDDEN    9 _DYNAMIC
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN   11 _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0000001c +0 TLS +GLOBAL DEFAULT +7 sg8
+ +[0-9]+: 0000007c +0 TLS +GLOBAL DEFAULT +8 bg8
+ +[0-9]+: 00000074 +0 TLS +GLOBAL DEFAULT +8 bg6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 00000068 +0 TLS +GLOBAL DEFAULT +8 bg3
+ +[0-9]+: 00000008 +0 TLS +GLOBAL DEFAULT +7 sg3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG7
+ +[0-9]+: 00000048 +0 TLS +GLOBAL HIDDEN +7 sh3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0000000c +0 TLS +GLOBAL DEFAULT +7 sg4
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: 00000010 +0 TLS +GLOBAL DEFAULT +7 sg5
+ +[0-9]+: 00000070 +0 TLS +GLOBAL DEFAULT +8 bg5
+ +[0-9]+: 00000058 +0 TLS +GLOBAL HIDDEN +7 sh7
+ +[0-9]+: 0000005c +0 TLS +GLOBAL HIDDEN +7 sh8
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1
+ +[0-9]+: 0+8049158 +0 FUNC +GLOBAL DEFAULT +6 _start
+ +[0-9]+: 0000004c +0 TLS +GLOBAL HIDDEN +7 sh4
+ +[0-9]+: 00000078 +0 TLS +GLOBAL DEFAULT +8 bg7
+ +[0-9]+: 00000050 +0 TLS +GLOBAL HIDDEN +7 sh5
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: 0+8049000 +0 FUNC +GLOBAL DEFAULT +6 fn2
+ +[0-9]+: 00000004 +0 TLS +GLOBAL DEFAULT +7 sg2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: 00000040 +0 TLS +GLOBAL HIDDEN +7 sh1
+ +[0-9]+: 00000014 +0 TLS +GLOBAL DEFAULT +7 sg6
+ +[0-9]+: 00000018 +0 TLS +GLOBAL DEFAULT +7 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 00000044 +0 TLS +GLOBAL HIDDEN +7 sh2
+ +[0-9]+: 00000054 +0 TLS +GLOBAL HIDDEN +7 sh6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG8
+ +[0-9]+: 00000064 +0 TLS +GLOBAL DEFAULT +8 bg2
+ +[0-9]+: 00000060 +0 TLS +GLOBAL DEFAULT +8 bg1
+ +[0-9]+: 0000006c +0 TLS +GLOBAL DEFAULT +8 bg4
Index: ld/testsuite/ld-i386/tlsbindesc.s
===================================================================
RCS file: ld/testsuite/ld-i386/tlsbindesc.s
diff -N ld/testsuite/ld-i386/tlsbindesc.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsbindesc.s 21 Sep 2005 06:13:18 -0000
@@ -0,0 +1,167 @@
+	/* Force .got aligned to 4K, so it very likely gets at 0x804a100
+	   (0x60 bytes .tdata and 0xa0 bytes .dynamic)  */
+	.section ".tdata", "awT", @progbits
+	.balign	4096
+	.globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8
+	.globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+	.hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	/* Force .text aligned to 4K, so it very likely gets at 0x8049000.  */
+	.text
+	.balign	4096
+	.globl	fn2
+	.type	fn2,@function
+fn2:
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	pushl	%eax
+	call	1f
+1:	popl	%ebx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable */
+	leal	sG1@tlsdesc(%ebx), %eax
+	call	*sG1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through @gottpoff too */
+	leal	sG2@tlsdesc(%ebx), %eax
+	call	*sG2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through @gotntpoff too */
+	leal	sG3@tlsdesc(%ebx), %eax
+	call	*sG3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through @gottpoff and @gotntpoff too */
+	leal	sG4@tlsdesc(%ebx), %eax
+	call	*sG4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with global variable defined in executable */
+	leal	sg1@tlsdesc(%ebx), %eax
+	call	*sg1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with local variable defined in executable */
+	leal	sl1@tlsdesc(%ebx), %eax
+	call	*sl1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with hidden variable defined in executable */
+	leal	sh1@tlsdesc(%ebx), %eax
+	call	*sh1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* LD -> LE */
+	leal	_TLS_MODULE_BASE_@tlsdesc(%ebx), %eax
+	call	*_TLS_MODULE_BASE_@tlscall(%eax)
+	nop;nop
+	leal	sl1@dtpoff(%eax), %edx
+	nop;nop
+	leal	sl2@dtpoff(%eax), %ecx
+	nop;nop;nop;nop
+
+	/* LD -> LE against hidden variables */
+	leal	_TLS_MODULE_BASE_@tlsdesc(%ebx), %eax
+	call	*_TLS_MODULE_BASE_@tlscall(%eax)
+	nop;nop
+	leal	sh1@dtpoff(%eax), %edx
+	nop;nop
+	leal	sh2@dtpoff(%eax), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sG2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sG4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sG3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sG4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE -> LE against global var defined in exec */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sg1@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE -> LE against local var */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sl1@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE -> LE against hidden var */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sh1@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* Direct access through %gs  */
+
+	/* @gotntpoff IE against global var  */
+	movl	sG5@gotntpoff(%ebx), %ecx
+	nop;nop
+	movl	%gs:(%ecx), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE->LE against local var  */
+	movl	sl5@gotntpoff(%ebx), %eax
+	nop;nop
+	movl	%gs:(%eax), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE->LE against hidden var  */
+	movl	sh5@gotntpoff(%ebx), %edx
+	nop;nop
+	movl	%gs:(%edx), %edx
+	nop;nop;nop;nop
+
+	movl    -4(%ebp), %ebx
+	leave
+	ret
Index: ld/testsuite/ld-i386/tlsbindesc.sd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsbindesc.sd
diff -N ld/testsuite/ld-i386/tlsbindesc.sd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsbindesc.sd 21 Sep 2005 06:13:18 -0000
@@ -0,0 +1,13 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --32
+#ld: -melf_i386 tmpdir/libtlslib.so
+#objdump: -sj.got
+#target: i?86-*-*
+
+.*:     file format elf32-i386
+
+Contents of section \.got:
+ 804a0e0 [0-9a-f]+ 00000000 00000000 [0-9a-f]+  .*
+ 804a0f0 00000000 00000000 00000000 00000000  .*
+ 804a100 00000000  +.*
Index: ld/testsuite/ld-i386/tlsbindesc.td
===================================================================
RCS file: ld/testsuite/ld-i386/tlsbindesc.td
diff -N ld/testsuite/ld-i386/tlsbindesc.td
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsbindesc.td 21 Sep 2005 06:13:18 -0000
@@ -0,0 +1,16 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --32
+#ld: -melf_i386 tmpdir/libtlslib.so
+#objdump: -sj.tdata
+#target: i?86-*-*
+
+.*:     file format elf32-i386
+
+Contents of section \.tdata:
+ 804a000 11000000 12000000 13000000 14000000  .*
+ 804a010 15000000 16000000 17000000 18000000  .*
+ 804a020 41000000 42000000 43000000 44000000  .*
+ 804a030 45000000 46000000 47000000 48000000  .*
+ 804a040 01010000 02010000 03010000 04010000  .*
+ 804a050 05010000 06010000 07010000 08010000  .*
Index: ld/testsuite/ld-i386/tlsdesc.dd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsdesc.dd
diff -N ld/testsuite/ld-i386/tlsdesc.dd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsdesc.dd 21 Sep 2005 06:13:18 -0000
@@ -0,0 +1,391 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --32
+#ld: -shared -melf_i386
+#objdump: -drj.text
+#target: i?86-*-*
+
+.*: +file format elf32-i386
+
+Disassembly of section .text:
+
+[0-9a-f]+ <fn1>:
+ [0-9a-f]+:	55[ 	]+push   %ebp
+ [0-9a-f]+:	89 e5[ 	]+mov    %esp,%ebp
+ [0-9a-f]+:	53[ 	]+push   %ebx
+ [0-9a-f]+:	50[ 	]+push   %eax
+ [0-9a-f]+:	e8 00 00 00 00[ 	]+call   [0-9a-f]+ <fn1\+0xa>
+ [0-9a-f]+:	5b[ 	]+pop    %ebx
+ [0-9a-f]+:	81 c3 9a 13 00 00[ 	]+add    \$0x[0-9a-f]+,%ebx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GDesc
+ [0-9a-f]+:	8d 83 24 00 00 00[ 	]+lea    0x24\(%ebx\),%eax
+#				->R_386_TLS_DESC	sg1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 f8 ff ff ff[ 	]+mov    0xfffffff8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sg2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gotntpoff too
+ [0-9a-f]+:	8b 83 c4 ff ff ff[ 	]+mov    0xffffffc4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sg3
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gottpoff and
+ [0-9a-f]+:	8b 83 d4 ff ff ff[ 	]+mov    0xffffffd4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sg4
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD against local variable
+ [0-9a-f]+:	8d 83 0c 00 00 00[ 	]+lea    0xc\(%ebx\),%eax
+#				->R_386_TLS_DESC	sl1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against local variable referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 b0 ff ff ff[ 	]+mov    0xffffffb0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sl2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against local variable referenced through @gotntpoff
+ [0-9a-f]+:	8b 83 b4 ff ff ff[ 	]+mov    0xffffffb4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sl3
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against local variable referenced through @gottpoff and
+ [0-9a-f]+:	8b 83 bc ff ff ff[ 	]+mov    0xffffffbc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sl4
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD against hidden and local variable
+ [0-9a-f]+:	8d 83 2c 00 00 00[ 	]+lea    0x2c\(%ebx\),%eax
+#				->R_386_TLS_DESC	sh1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden and local variable referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 fc ff ff ff[ 	]+mov    0xfffffffc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sh2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden and local variable referenced through @gotntpoff too
+ [0-9a-f]+:	8b 83 c8 ff ff ff[ 	]+mov    0xffffffc8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sh3
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden and local variable referenced through @gottpoff and @gotntpoff too
+ [0-9a-f]+:	8b 83 e8 ff ff ff[ 	]+mov    0xffffffe8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sh4
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD against hidden but not local variable
+ [0-9a-f]+:	8d 83 14 00 00 00[ 	]+lea    0x14\(%ebx\),%eax
+#				->R_386_TLS_DESC	sH1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden but not local variable referenced through
+ [0-9a-f]+:	8b 83 cc ff ff ff[ 	]+mov    0xffffffcc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sH2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden but not local variable referenced through
+ [0-9a-f]+:	8b 83 ec ff ff ff[ 	]+mov    0xffffffec\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sH3
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden but not local variable referenced through
+ [0-9a-f]+:	8b 83 e0 ff ff ff[ 	]+mov    0xffffffe0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sH4
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD
+ [0-9a-f]+:	8d 83 1c 00 00 00[ 	]+lea    0x1c\(%ebx\),%eax
+#				->R_386_TLS_DESC	_TLS_MODULE_BASE_
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 90 20 00 00 00[ 	]+lea    0x20\(%eax\),%edx
+#							sl1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 26 00 00 00[ 	]+lea    0x26\(%eax\),%ecx
+#							sl2+2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD against hidden and local variables
+ [0-9a-f]+:	8d 90 40 00 00 00[ 	]+lea    0x40\(%eax\),%edx
+#							sh1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 47 00 00 00[ 	]+lea    0x47\(%eax\),%ecx
+#							sh2+3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD against hidden but not local variables
+ [0-9a-f]+:	8d 90 60 00 00 00[ 	]+lea    0x60\(%eax\),%edx
+#							sH1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 65 00 00 00[ 	]+lea    0x65\(%eax\),%ecx
+#							sH2+1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b f8 ff ff ff[ 	]+sub    0xfffffff8\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	sg2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 d0 ff ff ff[ 	]+sub    0xffffffd0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sg4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b c4 ff ff ff[ 	]+add    0xffffffc4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sg3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 d4 ff ff ff[ 	]+add    0xffffffd4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sg4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b b0 ff ff ff[ 	]+sub    0xffffffb0\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	[0xdcffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 b8 ff ff ff[ 	]+sub    0xffffffb8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	[0xd4ffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b b4 ff ff ff[ 	]+add    0xffffffb4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	[0x28000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 bc ff ff ff[ 	]+add    0xffffffbc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	[0x2c000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against hidden and local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b fc ff ff ff[ 	]+sub    0xfffffffc\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	[0xbcffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against hidden and local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 e4 ff ff ff[ 	]+sub    0xffffffe4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	[0xb4ffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden and local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b c8 ff ff ff[ 	]+add    0xffffffc8\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	[0x48000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden and local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 e8 ff ff ff[ 	]+add    0xffffffe8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	[0x4c000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against hidden but not local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b cc ff ff ff[ 	]+sub    0xffffffcc\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	[0x9cffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against hidden but not local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 dc ff ff ff[ 	]+sub    0xffffffdc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	[0x94ffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden but not local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b ec ff ff ff[ 	]+add    0xffffffec\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	[0x68000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden but not local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 e0 ff ff ff[ 	]+add    0xffffffe0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	[0x6c000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  Direct access through %gs
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	8b 8b d8 ff ff ff[ 	]+mov    0xffffffd8\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sg5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 11[ 	]+mov    %gs:\(%ecx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against local var
+ [0-9a-f]+:	8b 83 c0 ff ff ff[ 	]+mov    0xffffffc0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	[0x30000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 10[ 	]+mov    %gs:\(%eax\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden and local var
+ [0-9a-f]+:	8b 93 f0 ff ff ff[ 	]+mov    0xfffffff0\(%ebx\),%edx
+#				->R_386_TLS_TPOFF	[0x50000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 12[ 	]+mov    %gs:\(%edx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden but not local var
+ [0-9a-f]+:	8b 8b f4 ff ff ff[ 	]+mov    0xfffffff4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	[0x70000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 11[ 	]+mov    %gs:\(%ecx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 5d fc[ 	]+mov    0xfffffffc\(%ebp\),%ebx
+ [0-9a-f]+:	c9[ 	]+leave *
+ [0-9a-f]+:	c3[ 	]+ret *
Index: ld/testsuite/ld-i386/tlsdesc.rd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsdesc.rd
diff -N ld/testsuite/ld-i386/tlsdesc.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsdesc.rd 21 Sep 2005 06:13:18 -0000
@@ -0,0 +1,155 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --32
+#ld: -shared -melf_i386
+#readelf: -Ssrl
+#target: i?86-*-*
+
+There are [0-9]+ section headers, starting at offset 0x.*:
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+  \[ 1\] \.hash +.*
+  \[ 2\] \.dynsym +.*
+  \[ 3\] \.dynstr +.*
+  \[ 4\] \.rel.dyn +.*
+  \[ 5\] \.rel.plt +.*
+  \[ 6\] \.text +.*
+  \[ 7\] \.tdata +PROGBITS +[0-9a-f]+ [0-9a-f]+ 000060 00 WAT  0   0  1
+  \[ 8\] \.tbss +NOBITS +[0-9aa-f]+ [0-9a-f]+ 000020 00 WAT  0   0  1
+  \[ 9\] \.dynamic +.*
+  \[10\] \.got +.*
+  \[11\] \.got.plt +.*
+  \[12\] \.shstrtab +.*
+  \[13\] \.symtab +.*
+  \[14\] \.strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x[0-9a-f]+
+There are [0-9]+ program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  LOAD.*
+  LOAD.*
+  DYNAMIC.*
+  TLS +0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x0+60 0x0+80 R +0x1
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +.hash .dynsym .dynstr .rel.dyn .rel.plt .text *
+   01 +.tdata .dynamic .got .got.plt *
+   02 +.dynamic *
+   03 +.tdata .tbss *
+
+Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 20 entries:
+ Offset +Info +Type +Sym.Value +Sym. Name
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+50e R_386_TLS_TPOFF   0+8   sg3
+[0-9a-f]+ +0+625 R_386_TLS_TPOFF32 0+c   sg4
+[0-9a-f]+ +0+60e R_386_TLS_TPOFF   0+c   sg4
+[0-9a-f]+ +0+70e R_386_TLS_TPOFF   0+10   sg5
+[0-9a-f]+ +0+b25 R_386_TLS_TPOFF32 0+4   sg2
+
+Relocation section '.rel.plt' at offset 0x[0-9a-f]+ contains 5 entries:
+ Offset     Info    Type            Sym.Value  Sym. Name
+[0-9a-f]+ +0+829 R_386_TLS_DESC * 0+   sg1
+[0-9a-f]+ +0+29 R_386_TLS_DESC *
+[0-9a-f]+ +0+29 R_386_TLS_DESC *
+[0-9a-f]+ +0+29 R_386_TLS_DESC *
+[0-9a-f]+ +0+29 R_386_TLS_DESC *
+
+Symbol table '.dynsym' contains 16 entries:
+ +Num: + Value  Size Type + Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +7 sg8
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +7 sg3
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +7 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +7 sg5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +6 fn1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +7 sg2
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +7 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +7 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 54 entries:
+ +Num: +Value  Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +[0-9]+: 0+20 +0 TLS +LOCAL  DEFAULT +7 sl1
+ +[0-9]+: 0+24 +0 TLS +LOCAL  DEFAULT +7 sl2
+ +[0-9]+: 0+28 +0 TLS +LOCAL  DEFAULT +7 sl3
+ +[0-9]+: 0+2c +0 TLS +LOCAL  DEFAULT +7 sl4
+ +[0-9]+: 0+30 +0 TLS +LOCAL  DEFAULT +7 sl5
+ +[0-9]+: 0+34 +0 TLS +LOCAL  DEFAULT +7 sl6
+ +[0-9]+: 0+38 +0 TLS +LOCAL  DEFAULT +7 sl7
+ +[0-9]+: 0+3c +0 TLS +LOCAL  DEFAULT +7 sl8
+ +[0-9]+: 0+60 +0 TLS +LOCAL  HIDDEN +8 sH1
+ +[0-9]+: 0+ +0 TLS +LOCAL  HIDDEN +7 _TLS_MODULE_BASE_
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _DYNAMIC
+ +[0-9]+: 0+48 +0 TLS +LOCAL  HIDDEN +7 sh3
+ +[0-9]+: 0+64 +0 TLS +LOCAL  HIDDEN +8 sH2
+ +[0-9]+: 0+78 +0 TLS +LOCAL  HIDDEN +8 sH7
+ +[0-9]+: 0+58 +0 TLS +LOCAL  HIDDEN +7 sh7
+ +[0-9]+: 0+5c +0 TLS +LOCAL  HIDDEN +7 sh8
+ +[0-9]+: 0+6c +0 TLS +LOCAL  HIDDEN +8 sH4
+ +[0-9]+: 0+4c +0 TLS +LOCAL  HIDDEN +7 sh4
+ +[0-9]+: 0+68 +0 TLS +LOCAL  HIDDEN +8 sH3
+ +[0-9]+: 0+50 +0 TLS +LOCAL  HIDDEN +7 sh5
+ +[0-9]+: 0+70 +0 TLS +LOCAL  HIDDEN +8 sH5
+ +[0-9]+: 0+74 +0 TLS +LOCAL  HIDDEN +8 sH6
+ +[0-9]+: 0+7c +0 TLS +LOCAL  HIDDEN +8 sH8
+ +[0-9]+: 0+40 +0 TLS +LOCAL  HIDDEN +7 sh1
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+44 +0 TLS +LOCAL  HIDDEN +7 sh2
+ +[0-9]+: 0+54 +0 TLS +LOCAL  HIDDEN +7 sh6
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +7 sg8
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +7 sg3
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +7 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +7 sg5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +6 fn1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +7 sg2
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +7 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +7 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
Index: ld/testsuite/ld-i386/tlsdesc.s
===================================================================
RCS file: ld/testsuite/ld-i386/tlsdesc.s
diff -N ld/testsuite/ld-i386/tlsdesc.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsdesc.s 21 Sep 2005 06:13:19 -0000
@@ -0,0 +1,276 @@
+	.section ".tdata", "awT", @progbits
+	.globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8
+	.globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+	.hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	.text
+	.globl	fn1
+	.type	fn1,@function
+fn1:
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	pushl	%eax
+	call	1f
+1:	popl	%ebx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sg1@tlsdesc(%ebx), %eax
+	call	*sg1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is referenced through @gottpoff too */
+	leal	sg2@tlsdesc(%ebx), %eax
+	call	*sg2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is referenced through @gotntpoff too */
+	leal	sg3@tlsdesc(%ebx), %eax
+	call	*sg3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is referenced through @gottpoff and
+	   @gotntpoff too */
+	leal	sg4@tlsdesc(%ebx), %eax
+	call	*sg4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD against local variable */
+	leal	sl1@tlsdesc(%ebx), %eax
+	call	*sl1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against local variable referenced through @gottpoff too */
+	leal	sl2@tlsdesc(%ebx), %eax
+	call	*sl2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against local variable referenced through @gotntpoff
+	   too */
+	leal	sl3@tlsdesc(%ebx), %eax
+	call	*sl3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against local variable referenced through @gottpoff and
+	   @gotntpoff too */
+	leal	sl4@tlsdesc(%ebx), %eax
+	call	*sl4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD against hidden and local variable */
+	leal	sh1@tlsdesc(%ebx), %eax
+	call	*sh1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden and local variable referenced through
+	   @gottpoff too */
+	leal	sh2@tlsdesc(%ebx), %eax
+	call	*sh2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden and local variable referenced through
+	   @gotntpoff too */
+	leal	sh3@tlsdesc(%ebx), %eax
+	call	*sh3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden and local variable referenced through
+	   @gottpoff and @gotntpoff too */
+	leal	sh4@tlsdesc(%ebx), %eax
+	call	*sh4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD against hidden but not local variable */
+	leal	sH1@tlsdesc(%ebx), %eax
+	call	*sH1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   @gottpoff too */
+	leal	sH2@tlsdesc(%ebx), %eax
+	call	*sH2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   @gotntpoff too */
+	leal	sH3@tlsdesc(%ebx), %eax
+	call	*sH3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   @gottpoff and @gotntpoff too */
+	leal	sH4@tlsdesc(%ebx), %eax
+	call	*sH4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* LD */
+	leal	_TLS_MODULE_BASE_@tlsdesc(%ebx), %eax
+	call	*_TLS_MODULE_BASE_@tlscall(%eax)
+	nop;nop
+	leal	sl1@dtpoff(%eax), %edx
+	nop;nop
+	leal	2+sl2@dtpoff(%eax), %ecx
+	nop;nop;nop;nop
+
+	/* LD against hidden and local variables */
+	leal	sh1@dtpoff(%eax), %edx
+	nop;nop
+	leal	sh2@dtpoff+3(%eax), %ecx
+	nop;nop;nop;nop
+
+	/* LD against hidden but not local variables */
+	leal	sH1@dtpoff(%eax), %edx
+	nop;nop
+	leal	sH2@dtpoff+1(%eax), %ecx
+	nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sg2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sg4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sg3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sg4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sl2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sl4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sl3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sl4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against hidden and local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sh2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against hidden and local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sh4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden and local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sh3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden and local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sh4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against hidden but not local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sH2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against hidden but not local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sH4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden but not local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sH3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden but not local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sH4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* Direct access through %gs  */
+
+	/* @gotntpoff IE against global var  */
+	movl	sg5@gotntpoff(%ebx), %ecx
+	nop;nop
+	movl	%gs:(%ecx), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against local var  */
+	movl	sl5@gotntpoff(%ebx), %eax
+	nop;nop
+	movl	%gs:(%eax), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden and local var  */
+	movl	sh5@gotntpoff(%ebx), %edx
+	nop;nop
+	movl	%gs:(%edx), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden but not local var  */
+	movl	sH5@gotntpoff(%ebx), %ecx
+	nop;nop
+	movl	%gs:(%ecx), %edx
+	nop;nop;nop;nop
+
+	movl    -4(%ebp), %ebx
+	leave
+	ret
Index: ld/testsuite/ld-i386/tlsdesc.sd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsdesc.sd
diff -N ld/testsuite/ld-i386/tlsdesc.sd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsdesc.sd 21 Sep 2005 06:13:19 -0000
@@ -0,0 +1,20 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --32
+#ld: -shared -melf_i386
+#objdump: -s -j.got -j.got.plt
+#target: i?86-*-*
+
+.*:     file format elf32-i386
+
+Contents of section \.got:
+ [0-9a-f]+ dcffffff 28000000 d4ffffff 2c000000  .*
+ [0-9a-f]+ 30000000 00000000 48000000 9cffffff  .*
+ [0-9a-f]+ 00000000 00000000 00000000 94ffffff  .*
+ [0-9a-f]+ 6c000000 b4ffffff 4c000000 68000000  .*
+ [0-9a-f]+ 50000000 70000000 00000000 bcffffff  .*
+Contents of section \.got\.plt:
+ [0-9a-f]+ ec150000 00000000 00000000 00000000  .*
+ [0-9a-f]+ 20000000 00000000 60000000 00000000  .*
+ [0-9a-f]+ 00000000 00000000 00000000 00000000  .*
+ [0-9a-f]+ 40000000 +.*
Index: ld/testsuite/ld-i386/tlsdesc.td
===================================================================
RCS file: ld/testsuite/ld-i386/tlsdesc.td
diff -N ld/testsuite/ld-i386/tlsdesc.td
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsdesc.td 21 Sep 2005 06:13:19 -0000
@@ -0,0 +1,16 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --32
+#ld: -shared -melf_i386
+#objdump: -sj.tdata
+#target: i?86-*-*
+
+.*:     file format elf32-i386
+
+Contents of section \.tdata:
+ [0-9a-f]+ 11000000 12000000 13000000 14000000  .*
+ [0-9a-f]+ 15000000 16000000 17000000 18000000  .*
+ [0-9a-f]+ 41000000 42000000 43000000 44000000  .*
+ [0-9a-f]+ 45000000 46000000 47000000 48000000  .*
+ [0-9a-f]+ 01010000 02010000 03010000 04010000  .*
+ [0-9a-f]+ 05010000 06010000 07010000 08010000  .*
Index: ld/testsuite/ld-i386/tlsgdesc.dd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsgdesc.dd
diff -N ld/testsuite/ld-i386/tlsgdesc.dd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsgdesc.dd 21 Sep 2005 06:13:19 -0000
@@ -0,0 +1,156 @@
+#source: tlsgdesc.s
+#as: --32
+#ld: -shared -melf_i386
+#objdump: -drj.text
+#target: i?86-*-*
+
+.*: +file format elf32-i386
+
+Disassembly of section .text:
+
+[0-9a-f]+ <fc1>:
+ [0-9a-f]+:	55[ 	]+push   %ebp
+ [0-9a-f]+:	89 e5[ 	]+mov    %esp,%ebp
+ [0-9a-f]+:	53[ 	]+push   %ebx
+ [0-9a-f]+:	50[ 	]+push   %eax
+ [0-9a-f]+:	e8 00 00 00 00[ 	]+call   [0-9a-f]+ <.*>
+ [0-9a-f]+:	5b[ 	]+pop    %ebx
+ [0-9a-f]+:	81 c3 be 11 00 00[ 	]+add    \$0x[0-9a-f]+,%ebx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b e0 ff ff ff[ 	]+sub    0xffffffe0\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	sG3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b f0 ff ff ff[ 	]+add    0xfffffff0\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sG4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD
+ [0-9a-f]+:	8d 04 1d f8 ff ff ff[ 	]+lea    0xfffffff8\(,%ebx,1\),%eax
+#				->R_386_TLS_DTPMOD32	sG1
+ [0-9a-f]+:	e8 a9 ff ff ff[ 	]+call   [0-9a-f]+ <___tls_get_addr@plt>
+#				->R_386_JUMP_SLOT	___tls_get_addr
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 83 18 00 00 00[ 	]+lea    0x18\(%ebx\),%eax
+#				->R_386_TLS_DESC	sG1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 83 10 00 00 00[ 	]+lea    0x10\(%ebx\),%eax
+#				->R_386_TLS_DESC	sG2
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 04 1d e8 ff ff ff[ 	]+lea    0xffffffe8\(,%ebx,1\),%eax
+#				->R_386_TLS_DTPMOD32	sG2
+ [0-9a-f]+:	e8 81 ff ff ff[ 	]+call   [0-9a-f]+ <___tls_get_addr@plt>
+#				->R_386_JUMP_SLOT	___tls_get_addr
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gottpoff too
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	2b 83 e0 ff ff ff[ 	]+sub    0xffffffe0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 83 e0 ff ff ff[ 	]+mov    0xffffffe0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG3
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gotntpoff too
+ [0-9a-f]+:	8b 83 f0 ff ff ff[ 	]+mov    0xfffffff0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG4
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	03 83 f0 ff ff ff[ 	]+add    0xfffffff0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gotntpoff too
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	03 83 e4 ff ff ff[ 	]+add    0xffffffe4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 83 e4 ff ff ff[ 	]+mov    0xffffffe4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG5
+ [0-9a-f]+:	89 c0[ 	]+mov    %eax,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 f4 ff ff ff[ 	]+mov    0xfffffff4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG6
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	2b 83 f4 ff ff ff[ 	]+sub    0xfffffff4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b e4 ff ff ff[ 	]+add    0xffffffe4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sG5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b f4 ff ff ff[ 	]+sub    0xfffffff4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	sG6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 5d fc[ 	]+mov    0xfffffffc\(%ebp\),%ebx
+ [0-9a-f]+:	c9[ 	]+leave *
+ [0-9a-f]+:	c3[ 	]+ret *
Index: ld/testsuite/ld-i386/tlsgdesc.rd
===================================================================
RCS file: ld/testsuite/ld-i386/tlsgdesc.rd
diff -N ld/testsuite/ld-i386/tlsgdesc.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsgdesc.rd 21 Sep 2005 06:13:19 -0000
@@ -0,0 +1,107 @@
+#source: tlsgdesc.s
+#as: --32
+#ld: -shared -melf_i386
+#readelf: -Ssrl
+#target: i?86-*-*
+
+There are [0-9]+ section headers, starting at offset 0x.*:
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+  \[ 1\] \.hash +.*
+  \[ 2\] \.dynsym +.*
+  \[ 3\] \.dynstr +.*
+  \[ 4\] \.rel.dyn +.*
+  \[ 5\] \.rel.plt +.*
+  \[ 6\] \.plt +.*
+  \[ 7\] \.text +.*
+  \[ 8\] \.dynamic +.*
+  \[ 9\] \.got +.*
+  \[10\] \.got.plt +.*
+  \[11\] \.shstrtab +.*
+  \[12\] \.symtab +.*
+  \[13\] \.strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x[0-9a-f]+
+There are [0-9]+ program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  LOAD.*
+  LOAD.*
+  DYNAMIC.*
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +.hash .dynsym .dynstr .rel.dyn .rel.plt .plt .text *
+   01 +.dynamic .got .got.plt *
+   02 +.dynamic *
+
+Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 8 entries:
+ Offset +Info +Type +Sym.Value +Sym. Name
+[0-9a-f]+ +0+225 R_386_TLS_TPOFF32 0+   sG3
+[0-9a-f]+ +0+30e R_386_TLS_TPOFF   0+   sG5
+[0-9a-f]+ +0+423 R_386_TLS_DTPMOD3 0+   sG2
+[0-9a-f]+ +0+424 R_386_TLS_DTPOFF3 0+   sG2
+[0-9a-f]+ +0+50e R_386_TLS_TPOFF   0+   sG4
+[0-9a-f]+ +0+725 R_386_TLS_TPOFF32 0+   sG6
+[0-9a-f]+ +0+923 R_386_TLS_DTPMOD3 0+   sG1
+[0-9a-f]+ +0+924 R_386_TLS_DTPOFF3 0+   sG1
+
+Relocation section '.rel.plt' at offset 0x[0-9a-f]+ contains 3 entries:
+ Offset     Info    Type            Sym.Value  Sym. Name
+[0-9a-f]+  0+c07 R_386_JUMP_SLOT   0+   ___tls_get_addr
+[0-9a-f]+  0+929 R_386_TLS_DESC    0+   sG1
+[0-9a-f]+  0+429 R_386_TLS_DESC    0+   sG2
+
+Symbol table '.dynsym' contains 13 entries:
+ +Num: + Value  Size Type + Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND ___tls_get_addr
+
+Symbol table '.symtab' contains 27 entries:
+ +Num: +Value  Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _DYNAMIC
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND ___tls_get_addr
Index: ld/testsuite/ld-i386/tlsgdesc.s
===================================================================
RCS file: ld/testsuite/ld-i386/tlsgdesc.s
diff -N ld/testsuite/ld-i386/tlsgdesc.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-i386/tlsgdesc.s 21 Sep 2005 06:13:19 -0000
@@ -0,0 +1,100 @@
+	.text
+	.globl	fc1
+	.type	fc1,@function
+fc1:
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	pushl	%eax
+	call	1f
+1:	popl	%ebx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sG3@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sG4@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sG1@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sG1@tlsdesc(%ebx), %eax
+	call	*sG1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sG2@tlsdesc(%ebx), %eax
+	call	*sG2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sG2@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE tpoff */
+	leal	sG3@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE tpoff */
+	leal	sG3@tlsdesc(%ebx), %eax
+	call	*sG3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE ntpoff */
+	leal	sG4@tlsdesc(%ebx), %eax
+	call	*sG4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE ntpoff */
+	leal	sG4@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE ntpoff */
+	leal	sG5@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE ntpoff */
+	leal	sG5@tlsdesc(%ebx), %eax
+	call	*sG5@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE tpoff */
+	leal	sG6@tlsdesc(%ebx), %eax
+	call	*sG6@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE tpoff */
+	leal	sG6@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sG5@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sG6@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	movl    -4(%ebp), %ebx
+	leave
+	ret
Index: ld/testsuite/ld-x86-64/tlsbindesc.dd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsbindesc.dd
diff -N ld/testsuite/ld-x86-64/tlsbindesc.dd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.dd 21 Sep 2005 06:13:19 -0000
@@ -0,0 +1,301 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -drj.text
+#target: x86_64-*-*
+
+# PT_TLS layout is:
+# Offset from   Offset from     Name
+# TCB base      TCB end
+# 0x00          -0xa0           sg1..sg8
+# 0x20          -0x80           sl1..sl8
+# 0x40          -0x60           sh1..sh8
+# 0x60          -0x40           bg1..bg8
+# 0x80          -0x20           bl1..bl8
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .text:
+
+0+401000 <fn2>:
+  [0-9a-f]+:	55[ 	]+push   %rbp
+  [0-9a-f]+:	48 89 e5[ 	]+mov    %rsp,%rbp
+#  GD -> IE because variable is not defined in executable
+  [0-9a-f]+:	48 8b 05 65 03 10 00[ 	]+mov    1049445\(%rip\),%rax +# 501370 <.*>
+#				-> R_X86_64_TPOFF64	sG1
+  [0-9a-f]+:	48 90[ 	]+rex64 nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable where
+#  the variable is referenced through IE too
+  [0-9a-f]+:	48 8b 05 48 03 10 00[ 	]+mov    1049416\(%rip\),%rax +# 501360 <.*>
+#				-> R_X86_64_TPOFF64	sG2
+  [0-9a-f]+:	48 90[ 	]+rex64 nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with global variable defined in executable
+  [0-9a-f]+:	48 c7 c0 60 ff ff ff[ 	]+mov    \$0xf+60,%rax
+#							sg1
+  [0-9a-f]+:	48 90[ 	]+rex64 nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with local variable defined in executable
+  [0-9a-f]+:	48 c7 c0 80 ff ff ff[ 	]+mov    \$0xf+80,%rax
+#							sl1
+  [0-9a-f]+:	48 90[ 	]+rex64 nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with hidden variable defined in executable
+  [0-9a-f]+:	48 c7 c0 a0 ff ff ff[ 	]+mov    \$0xf+a0,%rax
+#							sh1
+  [0-9a-f]+:	48 90[ 	]+rex64 nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LD -> LE
+  [0-9a-f]+:	48 c7 c0 60 ff ff ff[ 	]+mov    \$0xf+60,%rax
+  [0-9a-f]+:	48 90[ 	]+rex64 nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 90 81 ff ff ff[ 	]+lea    0xf+81\(%rax\),%rdx
+#							sl1+1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4c 8d 88 86 ff ff ff[ 	]+lea    0xf+86\(%rax\),%r9
+#							sl2+2
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LD -> LE against hidden variables
+  [0-9a-f]+:	48 8d 90 a0 ff ff ff[ 	]+lea    0xf+a0\(%rax\),%rdx
+#							sh1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 88 a7 ff ff ff[ 	]+lea    0xf+a7\(%rax\),%rcx
+#							sh2+3
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE against global var
+  [0-9a-f]+:	64 4c 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%r9
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4c 03 0d d6 02 10 00[ 	]+add    1049302\(%rip\),%r9 +# 501360 <.*>
+#				-> R_X86_64_TPOFF64	sG2
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against global var defined in exec
+  [0-9a-f]+:	64 4c 8b 14 25 00 00[ 	]+mov    %fs:0x0,%r10
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4d 8d 92 60 ff ff ff[ 	]+lea    0xf+60\(%r10\),%r10
+#							sg1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against local var
+  [0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 80 80 ff ff ff[ 	]+lea    0xf+80\(%rax\),%rax
+#							sl1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against hidden var
+  [0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 89 a0 ff ff ff[ 	]+lea    0xf+a0\(%rcx\),%rcx
+#							sh1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  Direct access through %fs
+#  IE against global var
+  [0-9a-f]+:	48 8b 0d 81 02 10 00[ 	]+mov    1049217\(%rip\),%rcx +# 501358 <.*>
+#				-> R_X86_64_TPOFF64	sG5
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 11[ 	]+mov    %fs:\(%rcx\),%rdx
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE->LE against local var
+  [0-9a-f]+:	49 c7 c3 90 ff ff ff[ 	]+mov    \$0xf+90,%r11
+#							sl5
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 4d 8b 23[ 	]+mov    %fs:\(%r11\),%r12
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE->LE against hidden var
+  [0-9a-f]+:	48 c7 c2 b0 ff ff ff[ 	]+mov    \$0xf+b0,%rdx
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 12[ 	]+mov    %fs:\(%rdx\),%rdx
+#							sh5
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	c9[ 	]+leaveq *
+  [0-9a-f]+:	c3[ 	]+retq *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+
+[0-9a-f]+ <_start>:
+  [0-9a-f]+:	55[ 	]+push   %rbp
+  [0-9a-f]+:	48 89 e5[ 	]+mov    %rsp,%rbp
+#  IE against global var
+  [0-9a-f]+:	64 4c 8b 1c 25 00 00[ 	]+mov    %fs:0x0,%r11
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4c 03 1d 4a 02 10 00[ 	]+add    1049162\(%rip\),%r11 +# 501368 <.*>
+#				-> R_X86_64_TPOFF64	sG6
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against global var defined in exec
+  [0-9a-f]+:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 92 d4 ff ff ff[ 	]+lea    0xf+d4\(%rdx\),%rdx
+#							bg6
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against local var
+  [0-9a-f]+:	64 4c 8b 24 25 00 00[ 	]+mov    %fs:0x0,%r12
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	49 81 c4 f4 ff ff ff[ 	]+add    \$0xf+f4,%r12
+#							bl6
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  direct %fs access IE -> LE against local var
+  [0-9a-f]+:	48 c7 c2 fc ff ff ff[ 	]+mov    \$0xf+fc,%rdx
+#							bl8
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 02[ 	]+mov    %fs:\(%rdx\),%rax
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against hidden but not local var
+  [0-9a-f]+:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 92 b4 ff ff ff[ 	]+lea    0xf+b4\(%rdx\),%rdx
+#							sh6
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  direct %fs access IE -> LE against hidden but not local var
+  [0-9a-f]+:	48 c7 c2 bc ff ff ff[ 	]+mov    \$0xf+bc,%rdx
+#							sh8
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 02[ 	]+mov    %fs:\(%rdx\),%rax
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, global var defined in exec
+  [0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 90 64 ff ff ff[ 	]+lea    0xf+64\(%rax\),%rdx
+#							sg2
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, local var, non-canonical sequence
+  [0-9a-f]+:	49 c7 c1 e6 ff ff ff[ 	]+mov    \$0xf+e6,%r9
+#							bl2+2
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4c 01 ca[ 	]+add    %r9,%rdx
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, hidden var defined in exec, non-canonical sequence
+  [0-9a-f]+:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 81 c2 a5 ff ff ff[ 	]+add    \$0xf+a5,%rdx
+#							sh2+1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  Direct %fs access
+#  LE, global var defined in exec
+  [0-9a-f]+:	64 48 8b 04 25 68 ff[ 	]+mov    %fs:0xf+68,%rax
+  [0-9a-f]+:	ff ff *
+#							sg3
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, local var
+  [0-9a-f]+:	64 4c 8b 14 25 eb ff[ 	]+mov    %fs:0xf+eb,%r10
+  [0-9a-f]+:	ff ff *
+#							bl3+3
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, hidden var defined in exec
+  [0-9a-f]+:	64 48 8b 14 25 a9 ff[ 	]+mov    %fs:0xf+a9,%rdx
+  [0-9a-f]+:	ff ff *
+#							sh3+1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	c9[ 	]+leaveq *
+  [0-9a-f]+:	c3[ 	]+retq *
Index: ld/testsuite/ld-x86-64/tlsbindesc.rd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsbindesc.rd
diff -N ld/testsuite/ld-x86-64/tlsbindesc.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.rd 21 Sep 2005 06:13:20 -0000
@@ -0,0 +1,141 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --64
+#ld: -shared -melf_x86_64
+#readelf: -WSsrl
+#target: x86_64-*-*
+
+There are 15 section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+  \[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 00 +0 +0 +0
+  \[ 1\] .interp +.*
+  \[ 2\] .hash +.*
+  \[ 3\] .dynsym +.*
+  \[ 4\] .dynstr +.*
+  \[ 5\] .rela.dyn +.*
+  \[ 6\] .text +PROGBITS +0+401000 0+1000 0+1f6 00 +AX +0 +0 +4096
+  \[ 7\] .tdata +PROGBITS +0+5011f6 0+11f6 0+60 00 WAT +0 +0 +1
+  \[ 8\] .tbss +NOBITS +0+501256 0+1256 0+40 00 WAT +0 +0 +1
+  \[ 9\] .dynamic +DYNAMIC +0+501258 0+1258 0+100 10 +WA +4 +0 +8
+  \[10\] .got +PROGBITS +0+501358 0+1358 0+20 08 +WA +0 +0 +8
+  \[11\] .got.plt +PROGBITS +0+501378 0+1378 0+18 08 +WA +0 +0 +8
+  \[12\] .shstrtab +.*
+  \[13\] .symtab +.*
+  \[14\] .strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x401108
+There are 6 program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  PHDR.*
+  INTERP.*
+.*Requesting program interpreter.*
+  LOAD +0x0+ 0x0+400000 0x0+400000 0x0+11f6 0x0+11f6 R E 0x100000
+  LOAD +0x0+11f6 0x0+5011f6 0x0+5011f6 0x0+19a 0x0+19a RW  0x100000
+  DYNAMIC +0x0+1258 0x0+501258 0x0+501258 0x0+100 0x0+100 RW  0x8
+  TLS +0x0+11f6 0x0+5011f6 0x0+5011f6 0x0+60 0x0+a0 R +0x1
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 *
+   01 +.interp *
+   02 +.interp .hash .dynsym .dynstr .rela.dyn .text *
+   03 +.tdata .dynamic .got .got.plt *
+   04 +.dynamic *
+   05 +.tdata .tbss *
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 4 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+0+501358  0+100000012 R_X86_64_TPOFF64 +0+ sG5 \+ 0
+0+501360  0+200000012 R_X86_64_TPOFF64 +0+ sG2 \+ 0
+0+501368  0+400000012 R_X86_64_TPOFF64 +0+ sG6 \+ 0
+0+501370  0+500000012 R_X86_64_TPOFF64 +0+ sG1 \+ 0
+
+Symbol table '.dynsym' contains 8 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+[0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: 0+[0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: 0+[0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 67 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +[0-9]+: 0+20 +0 TLS +LOCAL  DEFAULT +7 sl1
+ +[0-9]+: 0+24 +0 TLS +LOCAL  DEFAULT +7 sl2
+ +[0-9]+: 0+28 +0 TLS +LOCAL  DEFAULT +7 sl3
+ +[0-9]+: 0+2c +0 TLS +LOCAL  DEFAULT +7 sl4
+ +[0-9]+: 0+30 +0 TLS +LOCAL  DEFAULT +7 sl5
+ +[0-9]+: 0+34 +0 TLS +LOCAL  DEFAULT +7 sl6
+ +[0-9]+: 0+38 +0 TLS +LOCAL  DEFAULT +7 sl7
+ +[0-9]+: 0+3c +0 TLS +LOCAL  DEFAULT +7 sl8
+ +[0-9]+: 0+80 +0 TLS +LOCAL  DEFAULT +8 bl1
+ +[0-9]+: 0+84 +0 TLS +LOCAL  DEFAULT +8 bl2
+ +[0-9]+: 0+88 +0 TLS +LOCAL  DEFAULT +8 bl3
+ +[0-9]+: 0+8c +0 TLS +LOCAL  DEFAULT +8 bl4
+ +[0-9]+: 0+90 +0 TLS +LOCAL  DEFAULT +8 bl5
+ +[0-9]+: 0+94 +0 TLS +LOCAL  DEFAULT +8 bl6
+ +[0-9]+: 0+98 +0 TLS +LOCAL  DEFAULT +8 bl7
+ +[0-9]+: 0+9c +0 TLS +LOCAL  DEFAULT +8 bl8
+ +[0-9]+: 0+0 +0 TLS +LOCAL  HIDDEN +7 _TLS_MODULE_BASE_
+ +[0-9]+: 0+501258 +0 OBJECT  LOCAL  HIDDEN    9 _DYNAMIC
+ +[0-9]+: 0+501378 +0 OBJECT  LOCAL  HIDDEN   11 _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +7 sg8
+ +[0-9]+: 0+7c +0 TLS +GLOBAL DEFAULT +8 bg8
+ +[0-9]+: 0+74 +0 TLS +GLOBAL DEFAULT +8 bg6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+68 +0 TLS +GLOBAL DEFAULT +8 bg3
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +7 sg3
+ +[0-9]+: 0+48 +0 TLS +GLOBAL HIDDEN +7 sh3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +7 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +7 sg5
+ +[0-9]+: 0+70 +0 TLS +GLOBAL DEFAULT +8 bg5
+ +[0-9]+: 0+58 +0 TLS +GLOBAL HIDDEN +7 sh7
+ +[0-9]+: 0+5c +0 TLS +GLOBAL HIDDEN +7 sh8
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1
+ +[0-9]+: 0+401108 +0 FUNC +GLOBAL DEFAULT +6 _start
+ +[0-9]+: 0+4c +0 TLS +GLOBAL HIDDEN +7 sh4
+ +[0-9]+: 0+78 +0 TLS +GLOBAL DEFAULT +8 bg7
+ +[0-9]+: 0+50 +0 TLS +GLOBAL HIDDEN +7 sh5
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: 0+401000 +0 FUNC +GLOBAL DEFAULT +6 fn2
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +7 sg2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: 0+40 +0 TLS +GLOBAL HIDDEN +7 sh1
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +7 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +7 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 0+44 +0 TLS +GLOBAL HIDDEN +7 sh2
+ +[0-9]+: 0+54 +0 TLS +GLOBAL HIDDEN +7 sh6
+ +[0-9]+: 0+64 +0 TLS +GLOBAL DEFAULT +8 bg2
+ +[0-9]+: 0+60 +0 TLS +GLOBAL DEFAULT +8 bg1
+ +[0-9]+: 0+6c +0 TLS +GLOBAL DEFAULT +8 bg4
Index: ld/testsuite/ld-x86-64/tlsbindesc.s
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsbindesc.s
diff -N ld/testsuite/ld-x86-64/tlsbindesc.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.s 21 Sep 2005 06:13:20 -0000
@@ -0,0 +1,128 @@
+	/* Force .data aligned to 4K, so that .got very likely gets at
+	   0x5021a0 (0x60 bytes .tdata and 0x140 bytes .dynamic)  */
+	.data
+	.balign	4096
+	.section ".tdata", "awT", @progbits
+	.globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8
+	.globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+	.hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	/* Force .text aligned to 4K, so it very likely gets at 0x401000.  */
+	.text
+	.balign	4096
+	.globl	fn2
+	.type	fn2,@function
+fn2:
+	pushq	%rbp
+	movq	%rsp, %rbp
+
+	/* GD -> IE because variable is not defined in executable */
+	leaq	sG1@tlsdesc(%rip), %rax
+	call	*sG1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through IE too */
+	leaq	sG2@tlsdesc(%rip), %rax
+	call	*sG2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with global variable defined in executable */
+	leaq	sg1@tlsdesc(%rip), %rax
+	call	*sg1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with local variable defined in executable */
+	leaq	sl1@tlsdesc(%rip), %rax
+	call	*sl1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with hidden variable defined in executable */
+	leaq	sh1@tlsdesc(%rip), %rax
+	call	*sh1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* LD -> LE */
+	leaq	_TLS_MODULE_BASE_@tlsdesc(%rip), %rax
+	call	*_TLS_MODULE_BASE_@tlscall(%rax)
+	nop;nop
+	leaq	1+sl1@dtpoff(%rax), %rdx
+	nop;nop
+	leaq	sl2@dtpoff+2(%rax), %r9
+	nop;nop;nop;nop
+
+	/* LD -> LE against hidden variables */
+	leaq	sh1@dtpoff(%rax), %rdx
+	nop;nop
+	leaq	3+sh2@dtpoff(%rax), %rcx
+	nop;nop;nop;nop
+
+	/* IE against global var  */
+	movq	%fs:0, %r9
+	nop;nop
+	addq	sG2@gottpoff(%rip), %r9
+	nop;nop;nop;nop
+
+	/* IE -> LE against global var defined in exec */
+	movq	%fs:0, %r10
+	nop;nop
+	addq	sg1@gottpoff(%rip), %r10
+	nop;nop;nop;nop
+
+	/* IE -> LE against local var */
+	movq	%fs:0, %rax
+	nop;nop
+	addq	sl1@gottpoff(%rip), %rax
+	nop;nop;nop;nop
+
+	/* IE -> LE against hidden var */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sh1@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* Direct access through %fs  */
+
+	/* IE against global var  */
+	movq	sG5@gottpoff(%rip), %rcx
+	nop;nop
+	movq	%fs:(%rcx), %rdx
+	nop;nop;nop;nop
+
+	/* IE->LE against local var  */
+	movq	sl5@gottpoff(%rip), %r11
+	nop;nop
+	movq	%fs:(%r11), %r12
+	nop;nop;nop;nop
+
+	/* IE->LE against hidden var  */
+	movq	sh5@gottpoff(%rip), %rdx
+	nop;nop
+	movq	%fs:(%rdx), %rdx
+	nop;nop;nop;nop
+
+	leave
+	ret
Index: ld/testsuite/ld-x86-64/tlsbindesc.sd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsbindesc.sd
diff -N ld/testsuite/ld-x86-64/tlsbindesc.sd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.sd 21 Sep 2005 06:13:20 -0000
@@ -0,0 +1,12 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -sj.got
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Contents of section .got:
+ 501358 00000000 00000000 00000000 00000000  .*
+ 501368 00000000 00000000 00000000 00000000  .*
Index: ld/testsuite/ld-x86-64/tlsbindesc.td
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsbindesc.td
diff -N ld/testsuite/ld-x86-64/tlsbindesc.td
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.td 21 Sep 2005 06:13:20 -0000
@@ -0,0 +1,16 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -sj.tdata
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Contents of section .tdata:
+ 5011f6 11000000 12000000 13000000 14000000  .*
+ 501206 15000000 16000000 17000000 18000000  .*
+ 501216 41000000 42000000 43000000 44000000  .*
+ 501226 45000000 46000000 47000000 48000000  .*
+ 501236 01010000 02010000 03010000 04010000  .*
+ 501246 05010000 06010000 07010000 08010000  .*
Index: ld/testsuite/ld-x86-64/tlsdesc.dd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsdesc.dd
diff -N ld/testsuite/ld-x86-64/tlsdesc.dd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsdesc.dd 21 Sep 2005 06:13:20 -0000
@@ -0,0 +1,200 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -drj.text
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .text:
+
+0+[0-9a-f]+ <fn1>:
+ +[0-9a-f]+:	55[ 	]+push   %rbp
+ +[0-9a-f]+:	48 89 e5[ 	]+mov    %rsp,%rbp
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD
+ +[0-9a-f]+:	48 8d 05 89 03 10 00[ 	]+lea    1049481\(%rip\),%rax +# 101398 <.*>
+#				-> R_X86_64_TLSDESC	sg1
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through IE too
+ +[0-9a-f]+:	48 8b 05 1c 03 10 00[ 	]+mov    1049372\(%rip\),%rax +# 101338 <.*>
+#				-> R_X86_64_TPOFF64	sg2
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD against local variable
+ +[0-9a-f]+:	48 8d 05 3f 03 10 00[ 	]+lea    1049407\(%rip\),%rax +# 101368 <.*>
+#				-> R_X86_64_TLSDESC	[0 0x2000000000000000]
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against local variable referenced through IE too
+ +[0-9a-f]+:	48 8b 05 d2 02 10 00[ 	]+mov    1049298\(%rip\),%rax +# 101308 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x24
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD against hidden and local variable
+ +[0-9a-f]+:	48 8d 05 65 03 10 00[ 	]+lea    1049445\(%rip\),%rax +# 1013a8 <.*>
+#				-> R_X86_64_TLSDESC	[0 0x4000000000000000]
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden and local variable referenced through IE too
+ +[0-9a-f]+:	48 8b 05 f0 02 10 00[ 	]+mov    1049328\(%rip\),%rax +# 101340 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x44
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD against hidden but not local variable
+ +[0-9a-f]+:	48 8d 05 1b 03 10 00[ 	]+lea    1049371\(%rip\),%rax +# 101378 <.*>
+#				-> R_X86_64_TLSDESC	[0 0x6000000000000000]
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden but not local variable referenced through IE too
+ +[0-9a-f]+:	48 8b 05 ae 02 10 00[ 	]+mov    1049262\(%rip\),%rax +# 101318 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x64
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  LD
+ +[0-9a-f]+:	48 8d 05 11 03 10 00[ 	]+lea    1049361\(%rip\),%rax +# 101388 <.*>
+#				-> R_X86_64_TLSDESC	[0 0x000000000000000]
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8d 90 20 00 00 00[ 	]+lea    0x20\(%rax\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	4c 8d 88 26 00 00 00[ 	]+lea    0x26\(%rax\),%r9
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  LD against hidden and local variables
+ +[0-9a-f]+:	48 8d 90 40 00 00 00[ 	]+lea    0x40\(%rax\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8d 88 47 00 00 00[ 	]+lea    0x47\(%rax\),%rcx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  LD against hidden but not local variables
+ +[0-9a-f]+:	4c 8d a0 60 00 00 00[ 	]+lea    0x60\(%rax\),%r12
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8d 88 65 00 00 00[ 	]+lea    0x65\(%rax\),%rcx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against global var
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 71 02 10 00[ 	]+add    1049201\(%rip\),%rcx +# 101338 <.*>
+#				-> R_X86_64_TPOFF64	sg2
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against local var
+ +[0-9a-f]+:	64 4c 8b 34 25 00 00[ 	]+mov    %fs:0x0,%r14
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	4c 03 35 2b 02 10 00[ 	]+add    1049131\(%rip\),%r14 +# 101308 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x24
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against hidden and local var
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 4d 02 10 00[ 	]+add    1049165\(%rip\),%rcx +# 101340 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x44
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against hidden but not local var
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 0f 02 10 00[ 	]+add    1049103\(%rip\),%rcx +# 101318 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x64
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  Direct access through %fs
+#  IE against global var
+ +[0-9a-f]+:	48 8b 0d 0c 02 10 00[ 	]+mov    1049100\(%rip\),%rcx +# 101320 <.*>
+#				-> R_X86_64_TPOFF64	sg5
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 11[ 	]+mov    %fs:\(%rcx\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against local var
+ +[0-9a-f]+:	4c 8b 15 eb 01 10 00[ 	]+mov    1049067\(%rip\),%r10 +# 101310 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x30
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 4d 8b 22[ 	]+mov    %fs:\(%r10\),%r12
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against hidden and local var
+ +[0-9a-f]+:	48 8b 15 f2 01 10 00[ 	]+mov    1049074\(%rip\),%rdx +# 101328 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x50
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 12[ 	]+mov    %fs:\(%rdx\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against hidden but not local var
+ +[0-9a-f]+:	48 8b 0d e9 01 10 00[ 	]+mov    1049065\(%rip\),%rcx +# 101330 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x70
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 11[ 	]+mov    %fs:\(%rcx\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	c9[ 	]+leaveq *
+ +[0-9a-f]+:	c3[ 	]+retq *
+ +[0-9a-f]+:	90[ 	]+nop *
Index: ld/testsuite/ld-x86-64/tlsdesc.pd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsdesc.pd
diff -N ld/testsuite/ld-x86-64/tlsdesc.pd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsdesc.pd 21 Sep 2005 06:13:20 -0000
@@ -0,0 +1,26 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -drj.plt
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .plt:
+
+0000000000000470 <.*@plt-0x10>:
+ 470:	ff 35 e2 0e 10 00    	pushq  1052386\(%rip\)        # 101358 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ 476:	ff 25 e4 0e 10 00    	jmpq   \*1052388\(%rip\)        # 101360 <_GLOBAL_OFFSET_TABLE_\+0x10>
+ 47c:	90                   	nop    
+ 47d:	90                   	nop    
+ 47e:	90                   	nop    
+ 47f:	90                   	nop    
+0000000000000480 <.*@plt>:
+ 480:	ff 35 d2 0e 10 00    	pushq  1052370\(%rip\)        # 101358 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ 486:	ff 25 bc 0e 10 00    	jmpq   \*1052348\(%rip\)        # 101348 <_DYNAMIC\+0x190>
+ 48c:	90                   	nop    
+ 48d:	90                   	nop    
+ 48e:	90                   	nop    
+ 48f:	90                   	nop    
+
Index: ld/testsuite/ld-x86-64/tlsdesc.rd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsdesc.rd
diff -N ld/testsuite/ld-x86-64/tlsdesc.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsdesc.rd 21 Sep 2005 06:13:20 -0000
@@ -0,0 +1,164 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#readelf: -WSsrld
+#target: x86_64-*-*
+
+There are 16 section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+  \[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 00 +0 +0 +0
+  \[ 1\] .hash +.*
+  \[ 2\] .dynsym +.*
+  \[ 3\] .dynstr +.*
+  \[ 4\] .rela.dyn +.*
+  \[ 5\] .rela.plt +.*
+  \[ 6\] .plt +PROGBITS +0+470 0+470 0+20 10 +AX +0 +0 +4
+  \[ 7\] .text +PROGBITS +0+1000 0+1000 0+154 00 +AX +0 +0 4096
+  \[ 8\] .tdata +PROGBITS +0+101154 0+1154 0+60 00 WAT +0 +0 +1
+  \[ 9\] .tbss +NOBITS +0+1011b4 0+11b4 0+20 00 WAT +0 +0 +1
+  \[10\] .dynamic +DYNAMIC +0+1011b8 0+11b8 0+150 10 +WA +3 +0 +8
+  \[11\] .got +PROGBITS +0+101308 0+1308 0+48 08 +WA +0 +0 +8
+  \[12\] .got.plt +PROGBITS +0+101350 0+1350 0+68 08 +WA +0 +0 +8
+  \[13\] .shstrtab +.*
+  \[14\] .symtab +.*
+  \[15\] .strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x1000
+There are 4 program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  LOAD +0x0+ 0x0+ 0x0+ 0x[0-9a-f]+ 0x[0-9a-f]+ R E 0x100000
+  LOAD +0x0+1154 0x0+101154 0x0+101154 0x0+264 0x0+264 RW +0x100000
+  DYNAMIC +0x0+11b8 0x0+1011b8 0x0+1011b8 0x0+150 0x0+150 RW +0x8
+  TLS +0x0+1154 0x0+101154 0x0+101154 0x0+60 0x0+80 R +0x1
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +.hash .dynsym .dynstr .rela.dyn .rela.plt .plt .text *
+   01 +.tdata .dynamic .got .got.plt *
+   02 +.dynamic *
+   03 +.tdata .tbss *
+
+Dynamic section at offset 0x[0-9a-f]+ contains 16 entries:
+ +Tag +Type +Name/Value
+ 0x[0-9a-f]+ +\(HASH\).*
+ 0x[0-9a-f]+ +\(STRTAB\).*
+ 0x[0-9a-f]+ +\(SYMTAB\).*
+ 0x[0-9a-f]+ +\(STRSZ\).*
+ 0x[0-9a-f]+ +\(SYMENT\).*
+ 0x[0-9a-f]+ +\(PLTGOT\).*
+ 0x[0-9a-f]+ +\(PLTRELSZ\).*
+ 0x[0-9a-f]+ +\(PLTREL\).*
+ 0x[0-9a-f]+ +\(JMPREL\).*
+ 0x[0-9a-f]+ +\(TLSDESC_PLT\) +0x480
+ 0x[0-9a-f]+ +\(TLSDESC_GOT\) +0x101348
+ 0x[0-9a-f]+ +\(RELA\).*
+ 0x[0-9a-f]+ +\(RELASZ\).*
+ 0x[0-9a-f]+ +\(RELAENT\).*
+ 0x[0-9a-f]+ +\(FLAGS\).*
+ 0x[0-9a-f]+ +\(NULL\).*
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 8 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+0+101308  0+12 R_X86_64_TPOFF64 +0+24
+0+101310  0+12 R_X86_64_TPOFF64 +0+30
+0+101318  0+12 R_X86_64_TPOFF64 +0+64
+0+101328  0+12 R_X86_64_TPOFF64 +0+50
+0+101330  0+12 R_X86_64_TPOFF64 +0+70
+0+101340  0+12 R_X86_64_TPOFF64 +0+44
+0+101320  0+700000012 R_X86_64_TPOFF64 +0+10 sg5 \+ 0
+0+101338  0+b00000012 R_X86_64_TPOFF64 +0+4 sg2 \+ 0
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 5 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+0+101398  0+800000024 R_X86_64_TLSDESC +0+ sg1 \+ 0
+0+101368  0+24 R_X86_64_TLSDESC +0+20
+0+1013a8  0+24 R_X86_64_TLSDESC +0+40
+0+101378  0+24 R_X86_64_TLSDESC +0+60
+0+101388  0+24 R_X86_64_TLSDESC +0+
+
+Symbol table '.dynsym' contains 16 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +8 sg8
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +8 sg3
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +8 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +8 sg5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +8 sg1
+ +[0-9]+: 0+1000 +0 FUNC +GLOBAL DEFAULT +7 fn1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +8 sg2
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +8 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +8 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 55 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +15 *
+ +[0-9]+: 0+20 +0 TLS +LOCAL  DEFAULT +8 sl1
+ +[0-9]+: 0+24 +0 TLS +LOCAL  DEFAULT +8 sl2
+ +[0-9]+: 0+28 +0 TLS +LOCAL  DEFAULT +8 sl3
+ +[0-9]+: 0+2c +0 TLS +LOCAL  DEFAULT +8 sl4
+ +[0-9]+: 0+30 +0 TLS +LOCAL  DEFAULT +8 sl5
+ +[0-9]+: 0+34 +0 TLS +LOCAL  DEFAULT +8 sl6
+ +[0-9]+: 0+38 +0 TLS +LOCAL  DEFAULT +8 sl7
+ +[0-9]+: 0+3c +0 TLS +LOCAL  DEFAULT +8 sl8
+ +[0-9]+: 0+60 +0 TLS +LOCAL  HIDDEN +9 sH1
+ +[0-9]+: 0+ +0 TLS +LOCAL  HIDDEN +8 _TLS_MODULE_BASE_
+ +[0-9]+: 0+1011b8 +0 OBJECT  LOCAL  HIDDEN  ABS _DYNAMIC
+ +[0-9]+: 0+48 +0 TLS +LOCAL  HIDDEN +8 sh3
+ +[0-9]+: 0+64 +0 TLS +LOCAL  HIDDEN +9 sH2
+ +[0-9]+: 0+78 +0 TLS +LOCAL  HIDDEN +9 sH7
+ +[0-9]+: 0+58 +0 TLS +LOCAL  HIDDEN +8 sh7
+ +[0-9]+: 0+5c +0 TLS +LOCAL  HIDDEN +8 sh8
+ +[0-9]+: 0+6c +0 TLS +LOCAL  HIDDEN +9 sH4
+ +[0-9]+: 0+4c +0 TLS +LOCAL  HIDDEN +8 sh4
+ +[0-9]+: 0+68 +0 TLS +LOCAL  HIDDEN +9 sH3
+ +[0-9]+: 0+50 +0 TLS +LOCAL  HIDDEN +8 sh5
+ +[0-9]+: 0+70 +0 TLS +LOCAL  HIDDEN +9 sH5
+ +[0-9]+: 0+74 +0 TLS +LOCAL  HIDDEN +9 sH6
+ +[0-9]+: 0+7c +0 TLS +LOCAL  HIDDEN +9 sH8
+ +[0-9]+: 0+40 +0 TLS +LOCAL  HIDDEN +8 sh1
+ +[0-9]+: 0+101350 +0 OBJECT  LOCAL  HIDDEN  ABS _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+44 +0 TLS +LOCAL  HIDDEN +8 sh2
+ +[0-9]+: 0+54 +0 TLS +LOCAL  HIDDEN +8 sh6
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +8 sg8
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +8 sg3
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +8 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +8 sg5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +8 sg1
+ +[0-9]+: 0+1000 +0 FUNC +GLOBAL DEFAULT +7 fn1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +8 sg2
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +8 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +8 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
Index: ld/testsuite/ld-x86-64/tlsdesc.s
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsdesc.s
diff -N ld/testsuite/ld-x86-64/tlsdesc.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsdesc.s 21 Sep 2005 06:13:20 -0000
@@ -0,0 +1,157 @@
+	/* Force .data aligned to 4K, so .got very likely gets at 0x102190
+	   (0x60 bytes .tdata and 0x130 bytes .dynamic)  */
+        .data
+        .balign 4096
+	.section ".tdata", "awT", @progbits
+	.globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8
+	.globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+	.hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	/* Force .text aligned to 4K, so it very likely gets at 0x1000.  */
+	.text
+	.balign	4096
+	.globl	fn1
+	.type	fn1,@function
+fn1:
+	pushq	%rbp
+	movq	%rsp, %rbp
+	nop;nop;nop;nop
+
+	/* GD */
+	leaq	sg1@tlsdesc(%rip), %rax
+	call	*sg1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is referenced through IE too */
+	leaq	sg2@tlsdesc(%rip), %rax
+	call	*sg2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD against local variable */
+	leaq	sl1@tlsdesc(%rip), %rax
+	call	*sl1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against local variable referenced through IE too */
+	leaq	sl2@tlsdesc(%rip), %rax
+	call	*sl2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD against hidden and local variable */
+	leaq	sh1@tlsdesc(%rip), %rax
+	call	*sh1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden and local variable referenced through
+	   IE too */
+	leaq	sh2@tlsdesc(%rip), %rax
+	call	*sh2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD against hidden but not local variable */
+	leaq	sH1@tlsdesc(%rip), %rax
+	call	*sH1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   IE too */
+	leaq	sH2@tlsdesc(%rip), %rax
+	call	*sH2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* LD */
+	leaq	_TLS_MODULE_BASE_@tlsdesc(%rip), %rax
+	call	*_TLS_MODULE_BASE_@tlscall(%rax)
+	nop;nop
+	leaq	sl1@dtpoff(%rax), %rdx
+	nop;nop
+	leaq	2+sl2@dtpoff(%rax), %r9
+	nop;nop;nop;nop
+
+	/* LD against hidden and local variables */
+	leaq	sh1@dtpoff(%rax), %rdx
+	nop;nop
+	leaq	sh2@dtpoff+3(%rax), %rcx
+	nop;nop;nop;nop
+
+	/* LD against hidden but not local variables */
+	leaq	sH1@dtpoff(%rax), %r12
+	nop;nop
+	leaq	sH2@dtpoff+1(%rax), %rcx
+	nop;nop
+
+	/* IE against global var  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sg2@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* IE against local var  */
+	movq	%fs:0, %r14
+	nop;nop
+	addq	sl2@gottpoff(%rip), %r14
+	nop;nop;nop;nop
+
+	/* IE against hidden and local var  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sh2@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* IE against hidden but not local var  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sH2@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* Direct access through %fs  */
+
+	/* IE against global var  */
+	movq	sg5@gottpoff(%rip), %rcx
+	nop;nop
+	movq	%fs:(%rcx), %rdx
+	nop;nop;nop;nop
+
+	/* IE against local var  */
+	movq	sl5@gottpoff(%rip), %r10
+	nop;nop
+	movq	%fs:(%r10), %r12
+	nop;nop;nop;nop
+
+	/* IE against hidden and local var  */
+	movq	sh5@gottpoff(%rip), %rdx
+	nop;nop
+	movq	%fs:(%rdx), %rdx
+	nop;nop;nop;nop
+
+	/* IE against hidden but not local var  */
+	movq	sH5@gottpoff(%rip), %rcx
+	nop;nop
+	movq	%fs:(%rcx), %rdx
+	nop;nop;nop;nop
+
+	leave
+	ret
Index: ld/testsuite/ld-x86-64/tlsdesc.sd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsdesc.sd
diff -N ld/testsuite/ld-x86-64/tlsdesc.sd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsdesc.sd 21 Sep 2005 06:13:20 -0000
@@ -0,0 +1,23 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -s -j.got -j.got.plt
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Contents of section \.got:
+ 101308 00000000 00000000 00000000 00000000  .*
+ 101318 00000000 00000000 00000000 00000000  .*
+ 101328 00000000 00000000 00000000 00000000  .*
+ 101338 00000000 00000000 00000000 00000000  .*
+ 101348 00000000 00000000                    .*
+Contents of section \.got\.plt:
+ 101350 b8111000 00000000 00000000 00000000  .*
+ 101360 00000000 00000000 00000000 00000000  .*
+ 101370 00000000 00000000 00000000 00000000  .*
+ 101380 00000000 00000000 00000000 00000000  .*
+ 101390 00000000 00000000 00000000 00000000  .*
+ 1013a0 00000000 00000000 00000000 00000000  .*
+ 1013b0 00000000 00000000                    .*
Index: ld/testsuite/ld-x86-64/tlsdesc.td
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsdesc.td
diff -N ld/testsuite/ld-x86-64/tlsdesc.td
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsdesc.td 21 Sep 2005 06:13:20 -0000
@@ -0,0 +1,16 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -sj.tdata
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Contents of section .tdata:
+ 101154 11000000 12000000 13000000 14000000  .*
+ 101164 15000000 16000000 17000000 18000000  .*
+ 101174 41000000 42000000 43000000 44000000  .*
+ 101184 45000000 46000000 47000000 48000000  .*
+ 101194 01010000 02010000 03010000 04010000  .*
+ 1011a4 05010000 06010000 07010000 08010000  .*
Index: ld/testsuite/ld-x86-64/tlsgdesc.dd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsgdesc.dd
diff -N ld/testsuite/ld-x86-64/tlsgdesc.dd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsgdesc.dd 21 Sep 2005 06:13:20 -0000
@@ -0,0 +1,165 @@
+#source: tlsgdesc.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -drj.text
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .text:
+
+0+[0-9a-f]+ <fc1>:
+ +[0-9a-f]+:	55[ 	]+push   %rbp
+ +[0-9a-f]+:	48 89 e5[ 	]+mov    %rsp,%rbp
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# IE
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 5e 02 10 00[ 	]+add    1049182\(%rip\),%rcx +# 100660 <.*>
+#				-> R_X86_64_TPOFF64	sG3
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# IE
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 68 02 10 00[ 	]+add    1049192\(%rip\),%rcx +# 100680 <.*>
+#				-> R_X86_64_TPOFF64	sG4
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD, gd first
+ +[0-9a-f]+:	66 48 8d 3d 6c 02 10[ 	]+lea    1049196\(%rip\),%rdi +# 100690 <.*>
+ +[0-9a-f]+:	00 *
+#				-> R_X86_64_DTPMOD64	sG1
+ +[0-9a-f]+:	66[ 	]+data16
+ +[0-9a-f]+:	66[ 	]+data16
+ +[0-9a-f]+:	48 e8 9c ff ff ff[ 	]+rex64 callq  [0-9a-f]+ <.*>
+#				-> R_X86_64_JUMP_SLOT	__tls_get_addr
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8d 05 a1 02 10 00[ 	]+lea    1049249\(%rip\),%rax +# 1006d8 <.*>
+#				-> R_X86_64_TLSDESC	sG1
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD, desc first
+ +[0-9a-f]+:	48 8d 05 84 02 10 00[ 	]+lea    1049220\(%rip\),%rax +# 1006c8 <.*>
+#				-> R_X86_64_TLSDESC	sG2
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	66 48 8d 3d 1e 02 10[ 	]+lea    1049118\(%rip\),%rdi +# 100670 <.*>
+ +[0-9a-f]+:	00 *
+#				-> R_X86_64_DTPMOD64	sG2
+ +[0-9a-f]+:	66[ 	]+data16
+ +[0-9a-f]+:	66[ 	]+data16
+ +[0-9a-f]+:	48 e8 6e ff ff ff[ 	]+rex64 callq  [0-9a-f]+ <.*>
+#				-> R_X86_64_JUMP_SLOT	__tls_get_addr
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD -> IE, gd first, after IE use
+ +[0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	48 03 05 f2 01 10 00[ 	]+add    1049074\(%rip\),%rax +# 100660 <.*>
+#				-> R_X86_64_TPOFF64	sG3
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8b 05 e7 01 10 00[ 	]+mov    1049063\(%rip\),%rax +# 100660 <.*>
+#				-> R_X86_64_TPOFF64	sG3
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD -> IE, desc first, after IE use
+ +[0-9a-f]+:	48 8b 05 fa 01 10 00[ 	]+mov    1049082\(%rip\),%rax +# 100680 <.*>
+#				-> R_X86_64_TPOFF64	sG4
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	48 03 05 e4 01 10 00[ 	]+add    1049060\(%rip\),%rax +# 100680 <.*>
+#				-> R_X86_64_TPOFF64	sG4
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD -> IE, gd first, before IE use
+ +[0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	48 03 05 b8 01 10 00[ 	]+add    1049016\(%rip\),%rax +# 100668 <.*>
+#				-> R_X86_64_TPOFF64	sG5
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8b 05 ad 01 10 00[ 	]+mov    1049005\(%rip\),%rax +# 100668 <.*>
+#				-> R_X86_64_TPOFF64	sG5
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD -> IE, desc first, before IE use
+ +[0-9a-f]+:	48 8b 05 c0 01 10 00[ 	]+mov    1049024\(%rip\),%rax +# 100688 <.*>
+#				-> R_X86_64_TPOFF64	sG6
+ +[0-9a-f]+:	48 90[ 	]+rex64 nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	48 03 05 aa 01 10 00[ 	]+add    1049002\(%rip\),%rax +# 100688 <.*>
+#				-> R_X86_64_TPOFF64	sG6
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# IE
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 74 01 10 00[ 	]+add    1048948\(%rip\),%rcx +# 100668 <.*>
+#				-> R_X86_64_TPOFF64	sG5
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# IE
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 7e 01 10 00[ 	]+add    1048958\(%rip\),%rcx +# 100688 <.*>
+#				-> R_X86_64_TPOFF64	sG6
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	c9[ 	]+leaveq *
+ +[0-9a-f]+:	c3[ 	]+retq *
Index: ld/testsuite/ld-x86-64/tlsgdesc.rd
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsgdesc.rd
diff -N ld/testsuite/ld-x86-64/tlsgdesc.rd
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsgdesc.rd 21 Sep 2005 06:13:21 -0000
@@ -0,0 +1,107 @@
+#source: tlsgdesc.s
+#as: --64
+#ld: -shared -melf64_x86_64
+#readelf: -WSsrl
+#target: x86_64-*-*
+
+There are [0-9]+ section headers, starting at offset 0x.*:
+
+Section Headers:
+  \[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+  \[ 1\] \.hash +.*
+  \[ 2\] \.dynsym +.*
+  \[ 3\] \.dynstr +.*
+  \[ 4\] \.rela.dyn +.*
+  \[ 5\] \.rela.plt +.*
+  \[ 6\] \.plt +.*
+  \[ 7\] \.text +.*
+  \[ 8\] \.dynamic +.*
+  \[ 9\] \.got +.*
+  \[10\] \.got.plt +.*
+  \[11\] \.shstrtab +.*
+  \[12\] \.symtab +.*
+  \[13\] \.strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x[0-9a-f]+
+There are [0-9]+ program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  LOAD.*
+  LOAD.*
+  DYNAMIC.*
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +.hash .dynsym .dynstr .rela.dyn .rela.plt .plt .text *
+   01 +.dynamic .got .got.plt *
+   02 +.dynamic *
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 8 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+[0-9a-f]+  0+200000012 R_X86_64_TPOFF64 +0+ sG3 \+ 0
+[0-9a-f]+  0+300000012 R_X86_64_TPOFF64 +0+ sG5 \+ 0
+[0-9a-f]+  0+400000010 R_X86_64_DTPMOD64 +0+ sG2 \+ 0
+[0-9a-f]+  0+400000011 R_X86_64_DTPOFF64 +0+ sG2 \+ 0
+[0-9a-f]+  0+500000012 R_X86_64_TPOFF64 +0+ sG4 \+ 0
+[0-9a-f]+  0+800000012 R_X86_64_TPOFF64 +0+ sG6 \+ 0
+[0-9a-f]+  0+a00000010 R_X86_64_DTPMOD64 +0+ sG1 \+ 0
+[0-9a-f]+  0+a00000011 R_X86_64_DTPOFF64 +0+ sG1 \+ 0
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 3 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+[0-9a-f]+  0+600000007 R_X86_64_JUMP_SLOT +0+ __tls_get_addr \+ 0
+[0-9a-f]+  0+a00000024 R_X86_64_TLSDESC +0+ sG1 \+ 0
+[0-9a-f]+  0+400000024 R_X86_64_TLSDESC +0+ sG2 \+ 0
+
+Symbol table '.dynsym' contains 13 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_addr
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 27 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _DYNAMIC
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_addr
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
Index: ld/testsuite/ld-x86-64/tlsgdesc.s
===================================================================
RCS file: ld/testsuite/ld-x86-64/tlsgdesc.s
diff -N ld/testsuite/ld-x86-64/tlsgdesc.s
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ld/testsuite/ld-x86-64/tlsgdesc.s 21 Sep 2005 06:13:21 -0000
@@ -0,0 +1,106 @@
+	.text
+	.globl	fc1
+	.type	fc1,@function
+fc1:
+	pushq	%rbp
+	movq	%rsp, %rbp
+	nop;nop;nop;nop
+
+	/* IE against global var.  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sG3@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* IE against global var.  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sG4@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* GD, gd first.  */
+	.byte	0x66
+	leaq	sG1@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+	
+	leaq	sG1@tlsdesc(%rip), %rax
+	call	*sG1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD, desc first.  */
+	leaq	sG2@tlsdesc(%rip), %rax
+	call	*sG2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	.byte	0x66
+	leaq	sG2@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+	
+	/* GD -> IE, gd first, after IE use.  */
+	.byte	0x66
+	leaq	sG3@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+	
+	leaq	sG3@tlsdesc(%rip), %rax
+	call	*sG3@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE, desc first, after IE use.  */
+	leaq	sG4@tlsdesc(%rip), %rax
+	call	*sG4@tlscall(%rax)
+	nop;nop;nop;nop
+
+	.byte	0x66
+	leaq	sG4@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+	
+	/* GD -> IE, gd first, before IE use.  */
+	.byte	0x66
+	leaq	sG5@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+	
+	leaq	sG5@tlsdesc(%rip), %rax
+	call	*sG5@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE, desc first, before IE use.  */
+	leaq	sG6@tlsdesc(%rip), %rax
+	call	*sG6@tlscall(%rax)
+	nop;nop;nop;nop
+
+	.byte	0x66
+	leaq	sG6@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+	
+	/* IE against global var.  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sG5@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* IE against global var.  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sG6@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	leave
+	ret
Index: ld/testsuite/ld-x86-64/x86-64.exp
===================================================================
RCS file: /cvs/uberbaum/./ld/testsuite/ld-x86-64/x86-64.exp,v
retrieving revision 1.4
diff -u -p -r1.4 x86-64.exp
--- ld/testsuite/ld-x86-64/x86-64.exp 18 Jul 2005 06:23:40 -0000 1.4
+++ ld/testsuite/ld-x86-64/x86-64.exp 21 Sep 2005 06:13:23 -0000
@@ -1,5 +1,5 @@
 # Expect script for ld-x86_64 tests
-#   Copyright (C) 2002 Free Software Foundation
+#   Copyright (C) 2002, 2005 Free Software Foundation
 #
 # This file is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -39,6 +39,11 @@ set x86_64tests {
      {{readelf -WSsrl tlspic.rd} {objdump -drj.text tlspic.dd}
       {objdump -sj.got tlspic.sd} {objdump -sj.tdata tlspic.td}}
       "libtlspic.so"}
+    {"TLS descriptor -fpic -shared transitions" "-shared -melf_x86_64"
+     "--64" {tlsdesc.s tlspic2.s}
+     {{readelf -WSsrld tlsdesc.rd} {objdump -drj.text tlsdesc.dd}
+      {objdump "-s -j.got -j.got.plt" tlsdesc.sd} {objdump -sj.tdata tlsdesc.td}
+      {objdump -drj.plt tlsdesc.pd}} "libtlsdesc.so"}
     {"Helper shared library" "-shared -melf_x86_64"
      "--64" {tlslib.s} {} "libtlslib.so"}
     {"TLS -fpic and -fno-pic exec transitions"
@@ -46,6 +51,15 @@ set x86_64tests {
      {{readelf -WSsrl tlsbin.rd} {objdump -drj.text tlsbin.dd}
       {objdump -sj.got tlsbin.sd} {objdump -sj.tdata tlsbin.td}}
       "tlsbin"}
+    {"TLS descriptor -fpic and -fno-pic exec transitions"
+     "-melf_x86_64 tmpdir/libtlslib.so" "--64" {tlsbindesc.s tlsbin.s}
+     {{readelf -WSsrl tlsbindesc.rd} {objdump -drj.text tlsbindesc.dd}
+      {objdump -sj.got tlsbindesc.sd} {objdump -sj.tdata tlsbindesc.td}}
+      "tlsbindesc"}
+    {"TLS with global dynamic and descriptors"
+	"-shared -melf_x86_64" "--64" {tlsgdesc.s}
+     {{readelf -WSsrl tlsgdesc.rd} {objdump -drj.text tlsgdesc.dd}}
+      "libtlsgdesc.so"}
     {"TLS in debug sections" "-melf_x86_64"
      "--64" {tlsg.s}
      {{objdump -sj.debug_foobar tlsg.sd}} "tlsg"}


-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: RFC: TLS improvements for IA32 and AMD64/EM64T
  2005-09-22  7:53     ` Alexandre Oliva
@ 2006-01-14 17:58       ` Alexandre Oliva
  2006-01-18  1:45         ` Alan Modra
  0 siblings, 1 reply; 17+ messages in thread
From: Alexandre Oliva @ 2006-01-14 17:58 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 1260 bytes --]

On Sep 22, 2005, Alexandre Oliva <aoliva@redhat.com> wrote:

> On Sep 17, 2005, Alexandre Oliva <aoliva@redhat.com> wrote:
>> On Sep 16, 2005, Alexandre Oliva <aoliva@redhat.com> wrote:
>>> On Sep 16, 2005, Alexandre Oliva <aoliva@redhat.com> wrote:
>>>> Over the past few months, I've been working on porting to IA32 and
>>>> AMD64/EM64T the interesting bits of the TLS design I came up with for
>>>> FR-V, achieving some impressive speedups along with slight code size
>>>> reductions in the most common cases.
>>> Here's the patch.  Built and tested on x86_64-linux-gnu and
>>> i686-pc-linux-gnu.  Ok to install?

>> Updated patch, using different relocation numbers, and different
>> dynamic table numbers as well.  Same tests run and passed.  Ok to
>> install?

> Updated again.  Only significant change is that we no longer emit the
> new dynamic table entries on x86-64 if we're linking with -z now,
> since then we know we won't be resolving the relocations lazily, and
> so the entries are not used at all.

One more update.  This time I've modified a little bit the code
generated to pad relaxations, to get the best performance according to
my benchmarking (not a lot of difference, but still), and adjusted the
testsuite to match.

Ok to install?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: binutils-tlsdesc-2.patch --]
[-- Type: text/x-patch, Size: 196837 bytes --]

Index: bfd/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Introduce TLS descriptors for i386 and x86_64.
	* reloc.c (BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_386_TLS_DESC,
	BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_X86_64_GOTPC32_TLSDESC,
	BFD_RELOC_X86_64_TLSDESC, BFD_RELOC_X86_64_TLSDESC_CALL): New.
	* libbfd.h, bfd-in2.h: Rebuilt.
	* elf32-i386.c (elf_howto_table): New relocations.
	(R_386_tls): Adjust.
	(elf_i386_reloc_type_lookup): Map new relocations.
	(GOT_TLS_GDESC, GOT_TLS_GD_BOTH_P): New macros.
	(GOT_TLS_GD_P, GOT_TLS_GDESC_P, GOT_TLS_GD_ANY_P): New macros.
	(struct elf_i386_link_hash_entry): Add tlsdesc_got field.
	(struct elf_i386_obj_tdata): Add local_tlsdesc_gotent field.
	(elf_i386_local_tlsdesc_gotent): New macro.
	(struct elf_i386_link_hash_table): Add sgotplt_jump_table_size.
	(elf_i386_compute_jump_table_size): New macro.
	(link_hash_newfunc): Initialize tlsdesc_got.
	(elf_i386_link_hash_table_create): Set sgotplt_jump_table_size.
	(elf_i386_tls_transition): Handle R_386_TLS_GOTDESC and
	R_386_TLS_DESC_CALL.
	(elf_i386_check_relocs): Likewise.  Allocate space for
	local_tlsdesc_gotent.
	(elf_i386_gc_sweep_hook): Handle R_386_TLS_GOTDESC and
	R_386_TLS_DESC_CALL.
	(allocate_dynrelocs): Count function PLT relocations.  Reserve
	space for TLS descriptors and relocations.
	(elf_i386_size_dynamic_sections): Reserve space for TLS
	descriptors and relocations.  Set up sgotplt_jump_table_size.
	Don't zero reloc_count in srelplt.
	(elf_i386_always_size_sections): New.  Set up _TLS_MODULE_BASE_.
	(elf_i386_relocate_section): Handle R_386_TLS_GOTDESC and
	R_386_TLS_DESC_CALL.
	(elf_i386_finish_dynamic_symbol): Use GOT_TLS_GD_ANY_P.
	(elf_backend_always_size_sections): Define.
	* elf64-x86-64.c (x86_64_elf_howto): Add R_X86_64_GOTPC32_TLSDESC,
	R_X86_64_TLSDESC, R_X86_64_TLSDESC_CALL.
	(R_X86_64_standard): Adjust.
	(x86_64_reloc_map): Map new relocs.
	(elf64_x86_64_rtype_to_howto): New, split out of...
	(elf64_x86_64_info_to_howto): ... this function, and...
	(elf64_x86_64_reloc_type_lookup): ... use it to map elf_reloc_val.
	(GOT_TLS_GDESC, GOT_TLS_GD_BOTH_P): New macros.
	(GOT_TLS_GD_P, GOT_TLS_GDESC_P, GOT_TLS_GD_ANY_P): New macros.
	(struct elf64_x86_64_link_hash_entry): Add tlsdesc_got field.
	(struct elf64_x86_64_obj_tdata): Add local_tlsdesc_gotent field.
	(elf64_x86_64_local_tlsdesc_gotent): New macro.
	(struct elf64_x86_64_link_hash_table): Add tlsdesc_plt,
	tlsdesc_got and sgotplt_jump_table_size fields.
	(elf64_x86_64_compute_jump_table_size): New macro.
	(link_hash_newfunc): Initialize tlsdesc_got.
	(elf64_x86_64_link_hash_table_create): Initialize new fields.
	(elf64_x86_64_tls_transition): Handle R_X86_64_GOTPC32_TLSDESC and
	R_X86_64_TLSDESC_CALL.
	(elf64_x86_64_check_relocs): Likewise.  Allocate space for
	local_tlsdesc_gotent.
	(elf64_x86_64_gc_sweep_hook): Handle R_X86_64_GOTPC32_TLSDESC and
	R_X86_64_TLSDESC_CALL.
	(allocate_dynrelocs): Count function PLT relocations.  Reserve
	space for TLS descriptors and relocations.
	(elf64_x86_64_size_dynamic_sections): Reserve space for TLS
	descriptors and relocations.  Set up sgotplt_jump_table_size,
	tlsdesc_plt and tlsdesc_got.  Make room for them.  Don't zero
	reloc_count in srelplt.  Add dynamic entries for DT_TLSDESC_PLT
	and DT_TLSDESC_GOT.
	(elf64_x86_64_always_size_sections): New.  Set up
	_TLS_MODULE_BASE_.
	(elf64_x86_64_relocate_section): Handle R_386_TLS_GOTDESC and
	R_386_TLS_DESC_CALL.
	(elf64_x86_64_finish_dynamic_symbol): Use GOT_TLS_GD_ANY_P.
	(elf64_x86_64_finish_dynamic_sections): Set DT_TLSDESC_PLT and
	DT_TLSDESC_GOT.  Set up TLS descriptor lazy resolver PLT entry.
	(elf_backend_always_size_sections): Define.

Index: binutils/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Introduce TLS descriptors for i386 and x86_64.
	* readelf.c (get_dynamic_type): Handle DT_TLSDESC_GOT and
	DT_TLSDESC_PLT.

Index: gas/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Introduce TLS descriptors for i386 and x86_64.
	* config/tc-i386.c (tc_i386_fix_adjustable): Handle
	BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_386_TLS_DESC_CALL,
	BFD_RELOC_X86_64_GOTPC32_TLSDESC, BFD_RELOC_X86_64_TLSDESC_CALL.
	(optimize_disp): Emit fix up for BFD_RELOC_386_TLS_DESC_CALL and
	BFD_RELOC_X86_64_TLSDESC_CALL immediately, and clear the
	displacement bits.
	(build_modrm_byte): Set up zero modrm for TLS desc calls.
	(lex_got): Handle @tlsdesc and @tlscall.
	(md_apply_fix, tc_gen_reloc): Handle the new relocations.

Index: include/elf/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Introduce TLS descriptors for i386 and x86_64.
	* common.h (DT_TLSDESC_GOT, DT_TLSDESC_PLT): New.
	* i386.h (R_386_TLS_GOTDESC, R_386_TLS_DESC_CALL, R_386_TLS_DESC):
	New.
	* x86-64.h (R_X86_64_GOTPC32_TLSDESC, R_X86_64_TLSDESC_CALL,
	R_X86_64_TLSDESC): New.

Index: ld/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	Introduce TLS descriptors for i386 and x86_64.
	* ld-i386/i386.exp: Run on x86_64-*-linux* and amd64-*-linux*.
	Add new tests.
	* ld-i386/pcrel16.d: Add -melf_i386.
	* ld-i386/pcrel8.d: Likewise.
	* ld-i386/tlsbindesc.dd: New.
	* ld-i386/tlsbindesc.rd: New.
	* ld-i386/tlsbindesc.s: New.
	* ld-i386/tlsbindesc.sd: New.
	* ld-i386/tlsbindesc.td: New.
	* ld-i386/tlsdesc.dd: New.
	* ld-i386/tlsdesc.rd: New.
	* ld-i386/tlsdesc.s: New.
	* ld-i386/tlsdesc.sd: New.
	* ld-i386/tlsdesc.td: New.
	* ld-i386/tlsgdesc.dd: New.
	* ld-i386/tlsgdesc.rd: New.
	* ld-i386/tlsgdesc.s: New.
	* ld-x86-64/x86-64.exp: Run new tests.
	* ld-x86-64/tlsbindesc.dd: New.
	* ld-x86-64/tlsbindesc.rd: New.
	* ld-x86-64/tlsbindesc.s: New.
	* ld-x86-64/tlsbindesc.sd: New.
	* ld-x86-64/tlsbindesc.td: New.
	* ld-x86-64/tlsdesc.dd: New.
	* ld-x86-64/tlsdesc.pd: New.
	* ld-x86-64/tlsdesc.rd: New.
	* ld-x86-64/tlsdesc.s: New.
	* ld-x86-64/tlsdesc.sd: New.
	* ld-x86-64/tlsdesc.td: New.
	* ld-x86-64/tlsgdesc.dd: New.
	* ld-x86-64/tlsgdesc.rd: New.
	* ld-x86-64/tlsgdesc.s: New.

Index: bfd/bfd-in2.h
===================================================================
--- bfd/bfd-in2.h.orig	2006-01-13 18:13:26.000000000 -0500
+++ bfd/bfd-in2.h	2006-01-13 18:14:55.000000000 -0500
@@ -2661,6 +2661,9 @@
   BFD_RELOC_386_TLS_DTPMOD32,
   BFD_RELOC_386_TLS_DTPOFF32,
   BFD_RELOC_386_TLS_TPOFF32,
+  BFD_RELOC_386_TLS_GOTDESC,
+  BFD_RELOC_386_TLS_DESC_CALL,
+  BFD_RELOC_386_TLS_DESC,
 
 /* x86-64/elf relocations  */
   BFD_RELOC_X86_64_GOT32,
@@ -2681,6 +2684,9 @@
   BFD_RELOC_X86_64_TPOFF32,
   BFD_RELOC_X86_64_GOTOFF64,
   BFD_RELOC_X86_64_GOTPC32,
+  BFD_RELOC_X86_64_GOTPC32_TLSDESC,
+  BFD_RELOC_X86_64_TLSDESC_CALL,
+  BFD_RELOC_X86_64_TLSDESC,
 
 /* ns32k relocations  */
   BFD_RELOC_NS32K_IMM_8,
Index: bfd/elf32-i386.c
===================================================================
--- bfd/elf32-i386.c.orig	2006-01-13 18:13:26.000000000 -0500
+++ bfd/elf32-i386.c	2006-01-13 18:14:55.000000000 -0500
@@ -126,9 +126,19 @@
   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),
+  EMPTY_HOWTO (38),
+  HOWTO(R_386_TLS_GOTDESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_386_TLS_GOTDESC",
+	TRUE, 0xffffffff, 0xffffffff, FALSE),
+  HOWTO(R_386_TLS_DESC_CALL, 0, 0, 0, FALSE, 0, complain_overflow_dont,
+	bfd_elf_generic_reloc, "R_386_TLS_DESC_CALL",
+	FALSE, 0, 0, FALSE),
+  HOWTO(R_386_TLS_DESC, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
+	bfd_elf_generic_reloc, "R_386_TLS_DESC",
+	TRUE, 0xffffffff, 0xffffffff, FALSE),
 
   /* Another gap.  */
-#define R_386_tls (R_386_TLS_TPOFF32 + 1 - R_386_tls_offset)
+#define R_386_tls (R_386_TLS_DESC + 1 - R_386_tls_offset)
 #define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_tls)
 
 /* GNU extension to record C++ vtable hierarchy.  */
@@ -292,6 +302,18 @@
       TRACE ("BFD_RELOC_386_TLS_TPOFF32");
       return &elf_howto_table[R_386_TLS_TPOFF32 - R_386_tls_offset];
 
+    case BFD_RELOC_386_TLS_GOTDESC:
+      TRACE ("BFD_RELOC_386_TLS_GOTDESC");
+      return &elf_howto_table[R_386_TLS_GOTDESC - R_386_tls_offset];
+
+    case BFD_RELOC_386_TLS_DESC_CALL:
+      TRACE ("BFD_RELOC_386_TLS_DESC_CALL");
+      return &elf_howto_table[R_386_TLS_DESC_CALL - R_386_tls_offset];
+
+    case BFD_RELOC_386_TLS_DESC:
+      TRACE ("BFD_RELOC_386_TLS_DESC");
+      return &elf_howto_table[R_386_TLS_DESC - R_386_tls_offset];
+
     case BFD_RELOC_VTABLE_INHERIT:
       TRACE ("BFD_RELOC_VTABLE_INHERIT");
       return &elf_howto_table[R_386_GNU_VTINHERIT - R_386_vt_offset];
@@ -559,7 +581,20 @@
 #define GOT_TLS_IE_POS	5
 #define GOT_TLS_IE_NEG	6
 #define GOT_TLS_IE_BOTH 7
+#define GOT_TLS_GDESC	8
+#define GOT_TLS_GD_BOTH_P(type)						\
+  ((type) == (GOT_TLS_GD | GOT_TLS_GDESC))
+#define GOT_TLS_GD_P(type)						\
+  ((type) == GOT_TLS_GD || GOT_TLS_GD_BOTH_P (type))
+#define GOT_TLS_GDESC_P(type)						\
+  ((type) == GOT_TLS_GDESC || GOT_TLS_GD_BOTH_P (type))
+#define GOT_TLS_GD_ANY_P(type)						\
+  (GOT_TLS_GD_P (type) || GOT_TLS_GDESC_P (type))
   unsigned char tls_type;
+
+  /* Offset of the GOTPLT entry reserved for the TLS descriptor,
+     starting at the end of the jump table.  */
+  bfd_vma tlsdesc_got;
 };
 
 #define elf_i386_hash_entry(ent) ((struct elf_i386_link_hash_entry *)(ent))
@@ -570,6 +605,9 @@
 
   /* tls_type for each local got entry.  */
   char *local_got_tls_type;
+
+  /* GOTPLT entries for TLS descriptors.  */
+  bfd_vma *local_tlsdesc_gotent;
 };
 
 #define elf_i386_tdata(abfd) \
@@ -578,6 +616,9 @@
 #define elf_i386_local_got_tls_type(abfd) \
   (elf_i386_tdata (abfd)->local_got_tls_type)
 
+#define elf_i386_local_tlsdesc_gotent(abfd) \
+  (elf_i386_tdata (abfd)->local_tlsdesc_gotent)
+
 static bfd_boolean
 elf_i386_mkobject (bfd *abfd)
 {
@@ -620,6 +661,10 @@
     bfd_vma offset;
   } tls_ldm_got;
 
+  /* The amount of space used by the reserved portion of the sgotplt
+     section, plus whatever space is used by the jump slots.  */
+  bfd_vma sgotplt_jump_table_size;
+
   /* Small local sym to section mapping cache.  */
   struct sym_sec_cache sym_sec;
 };
@@ -629,6 +674,9 @@
 #define elf_i386_hash_table(p) \
   ((struct elf_i386_link_hash_table *) ((p)->hash))
 
+#define elf_i386_compute_jump_table_size(htab) \
+  ((htab)->srelplt->reloc_count * 4)
+
 /* Create an entry in an i386 ELF linker hash table.  */
 
 static struct bfd_hash_entry *
@@ -655,6 +703,7 @@
       eh = (struct elf_i386_link_hash_entry *) entry;
       eh->dyn_relocs = NULL;
       eh->tls_type = GOT_UNKNOWN;
+      eh->tlsdesc_got = (bfd_vma) -1;
     }
 
   return entry;
@@ -686,6 +735,7 @@
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
   ret->tls_ldm_got.refcount = 0;
+  ret->sgotplt_jump_table_size = 0;
   ret->sym_sec.abfd = NULL;
   ret->is_vxworks = 0;
   ret->srelplt2 = NULL;
@@ -845,6 +895,8 @@
   switch (r_type)
     {
     case R_386_TLS_GD:
+    case R_386_TLS_GOTDESC:
+    case R_386_TLS_DESC_CALL:
     case R_386_TLS_IE_32:
       if (is_local)
 	return R_386_TLS_LE_32;
@@ -949,6 +1001,8 @@
 
 	case R_386_GOT32:
 	case R_386_TLS_GD:
+	case R_386_TLS_GOTDESC:
+	case R_386_TLS_DESC_CALL:
 	  /* This symbol requires a global offset table entry.  */
 	  {
 	    int tls_type, old_tls_type;
@@ -958,6 +1012,9 @@
 	      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_GOTDESC:
+	      case R_386_TLS_DESC_CALL:
+		tls_type = GOT_TLS_GDESC; break;
 	      case R_386_TLS_IE_32:
 		if (ELF32_R_TYPE (rel->r_info) == r_type)
 		  tls_type = GOT_TLS_IE_NEG;
@@ -987,13 +1044,16 @@
 		    bfd_size_type size;
 
 		    size = symtab_hdr->sh_info;
-		    size *= (sizeof (bfd_signed_vma) + sizeof(char));
+		    size *= (sizeof (bfd_signed_vma)
+			     + sizeof (bfd_vma) + sizeof(char));
 		    local_got_refcounts = bfd_zalloc (abfd, size);
 		    if (local_got_refcounts == NULL)
 		      return FALSE;
 		    elf_local_got_refcounts (abfd) = local_got_refcounts;
+		    elf_i386_local_tlsdesc_gotent (abfd)
+		      = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info);
 		    elf_i386_local_got_tls_type (abfd)
-		      = (char *) (local_got_refcounts + symtab_hdr->sh_info);
+		      = (char *) (local_got_refcounts + 2 * symtab_hdr->sh_info);
 		  }
 		local_got_refcounts[r_symndx] += 1;
 		old_tls_type = elf_i386_local_got_tls_type (abfd) [r_symndx];
@@ -1004,11 +1064,14 @@
 	    /* If a TLS symbol is accessed using IE at least once,
 	       there is no point to use dynamic model for it.  */
 	    else if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN
-		     && (old_tls_type != GOT_TLS_GD
+		     && (! GOT_TLS_GD_ANY_P (old_tls_type)
 			 || (tls_type & GOT_TLS_IE) == 0))
 	      {
-		if ((old_tls_type & GOT_TLS_IE) && tls_type == GOT_TLS_GD)
+		if ((old_tls_type & GOT_TLS_IE) && GOT_TLS_GD_ANY_P (tls_type))
 		  tls_type = old_tls_type;
+		else if (GOT_TLS_GD_ANY_P (old_tls_type)
+			 && GOT_TLS_GD_ANY_P (tls_type))
+		  tls_type |= old_tls_type;
 		else
 		  {
 		    (*_bfd_error_handler)
@@ -1316,6 +1379,8 @@
 	  break;
 
 	case R_386_TLS_GD:
+	case R_386_TLS_GOTDESC:
+	case R_386_TLS_DESC_CALL:
 	case R_386_TLS_IE_32:
 	case R_386_TLS_IE:
 	case R_386_TLS_GOTIE:
@@ -1579,6 +1644,7 @@
 
 	  /* We also need to make an entry in the .rel.plt section.  */
 	  htab->srelplt->size += sizeof (Elf32_External_Rel);
+	  htab->srelplt->reloc_count++;
 
 	  if (htab->is_vxworks && !info->shared)
 	    {
@@ -1612,6 +1678,9 @@
       h->needs_plt = 0;
     }
 
+  eh = (struct elf_i386_link_hash_entry *) h;
+  eh->tlsdesc_got = (bfd_vma) -1;
+
   /* If R_386_TLS_{IE_32,IE,GOTIE} symbol is now local to the binary,
      make it a R_386_TLS_LE_32 requiring no TLS entry.  */
   if (h->got.refcount > 0
@@ -1635,11 +1704,22 @@
 	}
 
       s = htab->sgot;
-      h->got.offset = s->size;
-      s->size += 4;
-      /* R_386_TLS_GD needs 2 consecutive GOT slots.  */
-      if (tls_type == GOT_TLS_GD || tls_type == GOT_TLS_IE_BOTH)
-	s->size += 4;
+      if (GOT_TLS_GDESC_P (tls_type))
+	{
+	  eh->tlsdesc_got = htab->sgotplt->size
+	    - elf_i386_compute_jump_table_size (htab);
+	  htab->sgotplt->size += 8;
+	  h->got.offset = (bfd_vma) -2;
+	}
+      if (! GOT_TLS_GDESC_P (tls_type)
+	  || GOT_TLS_GD_P (tls_type))
+	{
+	  h->got.offset = s->size;
+	  s->size += 4;
+	  /* R_386_TLS_GD needs 2 consecutive GOT slots.  */
+	  if (GOT_TLS_GD_P (tls_type) || tls_type == GOT_TLS_IE_BOTH)
+	    s->size += 4;
+	}
       dyn = htab->elf.dynamic_sections_created;
       /* R_386_TLS_IE_32 needs one dynamic relocation,
 	 R_386_TLS_IE resp. R_386_TLS_GOTIE needs one dynamic relocation,
@@ -1648,21 +1728,23 @@
 	 global.  */
       if (tls_type == GOT_TLS_IE_BOTH)
 	htab->srelgot->size += 2 * sizeof (Elf32_External_Rel);
-      else if ((tls_type == GOT_TLS_GD && h->dynindx == -1)
+      else if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1)
 	       || (tls_type & GOT_TLS_IE))
 	htab->srelgot->size += sizeof (Elf32_External_Rel);
-      else if (tls_type == GOT_TLS_GD)
+      else if (GOT_TLS_GD_P (tls_type))
 	htab->srelgot->size += 2 * sizeof (Elf32_External_Rel);
-      else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-		|| h->root.type != bfd_link_hash_undefweak)
+      else if (! GOT_TLS_GDESC_P (tls_type)
+	       && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+		   || h->root.type != bfd_link_hash_undefweak)
 	       && (info->shared
 		   || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
 	htab->srelgot->size += sizeof (Elf32_External_Rel);
+      if (GOT_TLS_GDESC_P (tls_type))
+	htab->srelplt->size += sizeof (Elf32_External_Rel);
     }
   else
     h->got.offset = (bfd_vma) -1;
 
-  eh = (struct elf_i386_link_hash_entry *) h;
   if (eh->dyn_relocs == NULL)
     return TRUE;
 
@@ -1810,6 +1892,7 @@
       bfd_signed_vma *local_got;
       bfd_signed_vma *end_local_got;
       char *local_tls_type;
+      bfd_vma *local_tlsdesc_gotent;
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
       asection *srel;
@@ -1852,25 +1935,42 @@
       locsymcount = symtab_hdr->sh_info;
       end_local_got = local_got + locsymcount;
       local_tls_type = elf_i386_local_got_tls_type (ibfd);
+      local_tlsdesc_gotent = elf_i386_local_tlsdesc_gotent (ibfd);
       s = htab->sgot;
       srel = htab->srelgot;
-      for (; local_got < end_local_got; ++local_got, ++local_tls_type)
+      for (; local_got < end_local_got;
+	   ++local_got, ++local_tls_type, ++local_tlsdesc_gotent)
 	{
+	  *local_tlsdesc_gotent = (bfd_vma) -1;
 	  if (*local_got > 0)
 	    {
-	      *local_got = s->size;
-	      s->size += 4;
-	      if (*local_tls_type == GOT_TLS_GD
-		  || *local_tls_type == GOT_TLS_IE_BOTH)
-		s->size += 4;
+	      if (GOT_TLS_GDESC_P (*local_tls_type))
+		{
+		  *local_tlsdesc_gotent = htab->sgotplt->size
+		    - elf_i386_compute_jump_table_size (htab);
+		  htab->sgotplt->size += 8;
+		  *local_got = (bfd_vma) -2;
+		}
+	      if (! GOT_TLS_GDESC_P (*local_tls_type)
+		  || GOT_TLS_GD_P (*local_tls_type))
+		{
+		  *local_got = s->size;
+		  s->size += 4;
+		  if (GOT_TLS_GD_P (*local_tls_type)
+		      || *local_tls_type == GOT_TLS_IE_BOTH)
+		    s->size += 4;
+		}
 	      if (info->shared
-		  || *local_tls_type == GOT_TLS_GD
+		  || GOT_TLS_GD_ANY_P (*local_tls_type)
 		  || (*local_tls_type & GOT_TLS_IE))
 		{
 		  if (*local_tls_type == GOT_TLS_IE_BOTH)
 		    srel->size += 2 * sizeof (Elf32_External_Rel);
-		  else
+		  else if (GOT_TLS_GD_P (*local_tls_type)
+			   || ! GOT_TLS_GDESC_P (*local_tls_type))
 		    srel->size += sizeof (Elf32_External_Rel);
+		  if (GOT_TLS_GDESC_P (*local_tls_type))
+		    htab->srelplt->size += sizeof (Elf32_External_Rel);
 		}
 	    }
 	  else
@@ -1914,6 +2014,14 @@
      sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
 
+  /* For every jump slot reserved in the sgotplt, reloc_count is
+     incremented.  However, when we reserve space for TLS descriptors,
+     it's not incremented, so in order to compute the space reserved
+     for them, it suffices to multiply the reloc count by the jump
+     slot size.  */
+  if (htab->srelplt)
+    htab->sgotplt_jump_table_size = htab->srelplt->reloc_count * 4;
+
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
   relocs = FALSE;
@@ -1945,7 +2053,8 @@
 
 	  /* We use the reloc_count field as a counter if we need
 	     to copy relocs into the output file.  */
-	  s->reloc_count = 0;
+	  if (s != htab->srelplt)
+	    s->reloc_count = 0;
 	}
       else
 	{
@@ -2032,6 +2141,41 @@
   return TRUE;
 }
 
+static bfd_boolean
+elf_i386_always_size_sections (bfd *output_bfd,
+			       struct bfd_link_info *info)
+{
+  asection *tls_sec = elf_hash_table (info)->tls_sec;
+
+  if (tls_sec)
+    {
+      struct elf_link_hash_entry *tlsbase;
+
+      tlsbase = elf_link_hash_lookup (elf_hash_table (info),
+				      "_TLS_MODULE_BASE_",
+				      FALSE, FALSE, FALSE);
+
+      if (tlsbase && tlsbase->type == STT_TLS)
+	{
+	  struct bfd_link_hash_entry *bh = NULL;
+	  const struct elf_backend_data *bed
+	    = get_elf_backend_data (output_bfd);
+
+	  if (!(_bfd_generic_link_add_one_symbol
+		(info, output_bfd, "_TLS_MODULE_BASE_", BSF_LOCAL,
+		 tls_sec, 0, NULL, FALSE,
+		 bed->collect, &bh)))
+	    return FALSE;
+	  tlsbase = (struct elf_link_hash_entry *)bh;
+	  tlsbase->def_regular = 1;
+	  tlsbase->other = STV_HIDDEN;
+	  (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE);
+	}
+    }
+
+  return TRUE;
+}
+
 /* Set the correct type for an x86 ELF section.  We do this by the
    section name, which is a hack, but ought to work.  */
 
@@ -2109,6 +2253,7 @@
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
   bfd_vma *local_got_offsets;
+  bfd_vma *local_tlsdesc_gotents;
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
 
@@ -2116,6 +2261,7 @@
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (input_bfd);
   local_got_offsets = elf_local_got_offsets (input_bfd);
+  local_tlsdesc_gotents = elf_i386_local_tlsdesc_gotent (input_bfd);
 
   rel = relocs;
   relend = relocs + input_section->reloc_count;
@@ -2127,7 +2273,7 @@
       struct elf_link_hash_entry *h;
       Elf_Internal_Sym *sym;
       asection *sec;
-      bfd_vma off;
+      bfd_vma off, offplt;
       bfd_vma relocation;
       bfd_boolean unresolved_reloc;
       bfd_reloc_status_type r;
@@ -2549,6 +2695,8 @@
 	  /* Fall through */
 
 	case R_386_TLS_GD:
+	case R_386_TLS_GOTDESC:
+	case R_386_TLS_DESC_CALL:
 	case R_386_TLS_IE_32:
 	case R_386_TLS_GOTIE:
 	  r_type = elf_i386_tls_transition (info, r_type, h == NULL);
@@ -2563,7 +2711,9 @@
 	    }
 	  if (tls_type == GOT_TLS_IE)
 	    tls_type = GOT_TLS_IE_NEG;
-	  if (r_type == R_386_TLS_GD)
+	  if (r_type == R_386_TLS_GD
+	      || r_type == R_386_TLS_GOTDESC
+	      || r_type == R_386_TLS_DESC_CALL)
 	    {
 	      if (tls_type == GOT_TLS_IE_POS)
 		r_type = R_386_TLS_GOTIE;
@@ -2637,6 +2787,63 @@
 		  rel++;
 		  continue;
 		}
+	      else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC)
+		{
+		  /* GDesc -> LE transition.
+		     It's originally something like:
+		     leal x@tlsdesc(%ebx), %eax
+
+		     leal x@ntpoff, %eax
+
+		     Registers other than %eax may be set up here.  */
+
+		  unsigned int val, type;
+		  bfd_vma roff;
+
+		  /* First, make sure it's a leal adding ebx to a
+		     32-bit offset into any register, although it's
+		     probably almost always going to be eax.  */
+		  roff = rel->r_offset;
+		  BFD_ASSERT (roff >= 2);
+		  type = bfd_get_8 (input_bfd, contents + roff - 2);
+		  BFD_ASSERT (type == 0x8d);
+		  val = bfd_get_8 (input_bfd, contents + roff - 1);
+		  BFD_ASSERT ((val & 0xc7) == 0x83);
+		  BFD_ASSERT (roff + 4 <= input_section->size);
+
+		  /* Now modify the instruction as appropriate.  */
+		  /* aoliva FIXME: remove the above and xor the byte
+		     below with 0x86.  */
+		  bfd_put_8 (output_bfd, val ^ 0x86,
+			     contents + roff - 1);
+		  bfd_put_32 (output_bfd, -tpoff (info, relocation),
+			      contents + roff);
+		  continue;
+		}
+	      else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL)
+		{
+		  /* GDesc -> LE transition.
+		     It's originally:
+		     call *(%eax)
+		     Turn it into:
+		     nop; nop  */
+
+		  unsigned int val, type;
+		  bfd_vma roff;
+
+		  /* First, make sure it's a call *(%eax).  */
+		  roff = rel->r_offset;
+		  BFD_ASSERT (roff + 2 <= input_section->size);
+		  type = bfd_get_8 (input_bfd, contents + roff);
+		  BFD_ASSERT (type == 0xff);
+		  val = bfd_get_8 (input_bfd, contents + roff + 1);
+		  BFD_ASSERT (val == 0x10);
+
+		  /* Now modify the instruction as appropriate.  */
+		  bfd_put_8 (output_bfd, 0x90, contents + roff);
+		  bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
+		  continue;
+		}
 	      else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_IE)
 		{
 		  unsigned int val, type;
@@ -2751,13 +2958,17 @@
 	    abort ();
 
 	  if (h != NULL)
-	    off = h->got.offset;
+	    {
+	      off = h->got.offset;
+	      offplt = elf_i386_hash_entry (h)->tlsdesc_got;
+	    }
 	  else
 	    {
 	      if (local_got_offsets == NULL)
 		abort ();
 
 	      off = local_got_offsets[r_symndx];
+	      offplt = local_tlsdesc_gotents[r_symndx];
 	    }
 
 	  if ((off & 1) != 0)
@@ -2767,35 +2978,77 @@
 	      Elf_Internal_Rela outrel;
 	      bfd_byte *loc;
 	      int dr_type, indx;
+	      asection *sreloc;
 
 	      if (htab->srelgot == NULL)
 		abort ();
 
+	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
+
+	      if (GOT_TLS_GDESC_P (tls_type))
+		{
+		  outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_DESC);
+		  BFD_ASSERT (htab->sgotplt_jump_table_size + offplt + 8
+			      <= htab->sgotplt->size);
+		  outrel.r_offset = (htab->sgotplt->output_section->vma
+				     + htab->sgotplt->output_offset
+				     + offplt
+				     + htab->sgotplt_jump_table_size);
+		  sreloc = htab->srelplt;
+		  loc = sreloc->contents;
+		  loc += sreloc->reloc_count++
+		    * sizeof (Elf32_External_Rel);
+		  BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
+			      <= sreloc->contents + sreloc->size);
+		  bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
+		  if (indx == 0)
+		    {
+		      BFD_ASSERT (! unresolved_reloc);
+		      bfd_put_32 (output_bfd,
+				  relocation - dtpoff_base (info),
+				  htab->sgotplt->contents + offplt
+				  + htab->sgotplt_jump_table_size + 4);
+		    }
+		  else
+		    {
+		      bfd_put_32 (output_bfd, 0,
+				  htab->sgotplt->contents + offplt
+				  + htab->sgotplt_jump_table_size + 4);
+		    }
+		}
+
+	      sreloc = htab->srelgot;
+
 	      outrel.r_offset = (htab->sgot->output_section->vma
 				 + htab->sgot->output_offset + off);
 
-	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
-	      if (r_type == R_386_TLS_GD)
+	      if (GOT_TLS_GD_P (tls_type))
 		dr_type = R_386_TLS_DTPMOD32;
+	      else if (GOT_TLS_GDESC_P (tls_type))
+		goto dr_done;
 	      else if (tls_type == GOT_TLS_IE_POS)
 		dr_type = R_386_TLS_TPOFF;
 	      else
 		dr_type = R_386_TLS_TPOFF32;
+
 	      if (dr_type == R_386_TLS_TPOFF && indx == 0)
 		bfd_put_32 (output_bfd, relocation - dtpoff_base (info),
 			    htab->sgot->contents + off);
 	      else if (dr_type == R_386_TLS_TPOFF32 && indx == 0)
 		bfd_put_32 (output_bfd, dtpoff_base (info) - relocation,
 			    htab->sgot->contents + off);
-	      else
+	      else if (dr_type != R_386_TLS_DESC)
 		bfd_put_32 (output_bfd, 0,
 			    htab->sgot->contents + off);
 	      outrel.r_info = ELF32_R_INFO (indx, dr_type);
-	      loc = htab->srelgot->contents;
-	      loc += htab->srelgot->reloc_count++ * sizeof (Elf32_External_Rel);
+
+	      loc = sreloc->contents;
+	      loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel);
+	      BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
+			  <= sreloc->contents + sreloc->size);
 	      bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
 
-	      if (r_type == R_386_TLS_GD)
+	      if (GOT_TLS_GD_P (tls_type))
 		{
 		  if (indx == 0)
 		    {
@@ -2811,8 +3064,10 @@
 		      outrel.r_info = ELF32_R_INFO (indx,
 						    R_386_TLS_DTPOFF32);
 		      outrel.r_offset += 4;
-		      htab->srelgot->reloc_count++;
+		      sreloc->reloc_count++;
 		      loc += sizeof (Elf32_External_Rel);
+		      BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
+				  <= sreloc->contents + sreloc->size);
 		      bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
 		    }
 		}
@@ -2823,25 +3078,33 @@
 			      htab->sgot->contents + off + 4);
 		  outrel.r_info = ELF32_R_INFO (indx, R_386_TLS_TPOFF);
 		  outrel.r_offset += 4;
-		  htab->srelgot->reloc_count++;
+		  sreloc->reloc_count++;
 		  loc += sizeof (Elf32_External_Rel);
 		  bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
 		}
 
+	    dr_done:
 	      if (h != NULL)
 		h->got.offset |= 1;
 	      else
 		local_got_offsets[r_symndx] |= 1;
 	    }
 
-	  if (off >= (bfd_vma) -2)
+	  if (off >= (bfd_vma) -2
+	      && ! GOT_TLS_GDESC_P (tls_type))
 	    abort ();
-	  if (r_type == ELF32_R_TYPE (rel->r_info))
+	  if (r_type == R_386_TLS_GOTDESC
+	      || r_type == R_386_TLS_DESC_CALL)
+	    {
+	      relocation = htab->sgotplt_jump_table_size + offplt;
+	      unresolved_reloc = FALSE;
+	    }
+	  else if (r_type == ELF32_R_TYPE (rel->r_info))
 	    {
 	      bfd_vma g_o_t = htab->sgotplt->output_section->vma
 			      + htab->sgotplt->output_offset;
 	      relocation = htab->sgot->output_section->vma
-			   + htab->sgot->output_offset + off - g_o_t;
+		+ htab->sgot->output_offset + off - g_o_t;
 	      if ((r_type == R_386_TLS_IE || r_type == R_386_TLS_GOTIE)
 		  && tls_type == GOT_TLS_IE_BOTH)
 		relocation += 4;
@@ -2849,7 +3112,7 @@
 		relocation += g_o_t;
 	      unresolved_reloc = FALSE;
 	    }
-	  else
+	  else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD)
 	    {
 	      unsigned int val, type;
 	      bfd_vma roff;
@@ -2913,6 +3176,94 @@
 	      rel++;
 	      continue;
 	    }
+	  else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_GOTDESC)
+	    {
+	      /* GDesc -> IE transition.
+		 It's originally something like:
+		 leal x@tlsdesc(%ebx), %eax
+
+		 Change it to:
+		 movl x@gotntpoff(%ebx), %eax # before nop; nop
+		 or:
+		 movl x@gottpoff(%ebx), %eax # before negl %eax
+
+		 Registers other than %eax may be set up here.  */
+
+	      unsigned int val, type;
+	      bfd_vma roff;
+
+	      /* First, make sure it's a leal adding ebx to a 32-bit
+		 offset into any register, although it's probably
+		 almost always going to be eax.  */
+	      roff = rel->r_offset;
+	      BFD_ASSERT (roff >= 2);
+	      type = bfd_get_8 (input_bfd, contents + roff - 2);
+	      BFD_ASSERT (type == 0x8d);
+	      val = bfd_get_8 (input_bfd, contents + roff - 1);
+	      BFD_ASSERT ((val & 0xc7) == 0x83);
+	      BFD_ASSERT (roff + 4 <= input_section->size);
+
+	      /* Now modify the instruction as appropriate.  */
+	      /* To turn a leal into a movl in the form we use it, it
+		 suffices to change the first byte from 0x8d to 0x8b.
+		 aoliva FIXME: should we decide to keep the leal, all
+		 we have to do is remove the statement below, and
+		 adjust the relaxation of R_386_TLS_DESC_CALL.  */
+	      bfd_put_8 (output_bfd, 0x8b, contents + roff - 2);
+
+	      if (tls_type == GOT_TLS_IE_BOTH)
+		off += 4;
+
+	      bfd_put_32 (output_bfd,
+			  htab->sgot->output_section->vma
+			  + htab->sgot->output_offset + off
+			  - htab->sgotplt->output_section->vma
+			  - htab->sgotplt->output_offset,
+			  contents + roff);
+	      continue;
+	    }
+	  else if (ELF32_R_TYPE (rel->r_info) == R_386_TLS_DESC_CALL)
+	    {
+	      /* GDesc -> IE transition.
+		 It's originally:
+		 call *(%eax)
+
+		 Change it to:
+		 nop; nop
+		 or
+		 negl %eax
+		 depending on how we transformed the TLS_GOTDESC above.
+	      */
+
+	      unsigned int val, type;
+	      bfd_vma roff;
+
+	      /* First, make sure it's a call *(%eax).  */
+	      roff = rel->r_offset;
+	      BFD_ASSERT (roff + 2 <= input_section->size);
+	      type = bfd_get_8 (input_bfd, contents + roff);
+	      BFD_ASSERT (type == 0xff);
+	      val = bfd_get_8 (input_bfd, contents + roff + 1);
+	      BFD_ASSERT (val == 0x10);
+
+	      /* Now modify the instruction as appropriate.  */
+	      if (tls_type != GOT_TLS_IE_NEG)
+		{
+		  /* nop; nop */
+		  bfd_put_8 (output_bfd, 0x90, contents + roff);
+		  bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
+		}
+	      else
+		{
+		  /* negl %eax */
+		  bfd_put_8 (output_bfd, 0xf7, contents + roff);
+		  bfd_put_8 (output_bfd, 0xd8, contents + roff + 1);
+		}
+
+	      continue;
+	    }
+	  else
+	    BFD_ASSERT (FALSE);
 	  break;
 
 	case R_386_TLS_LDM:
@@ -3220,7 +3571,7 @@
     }
 
   if (h->got.offset != (bfd_vma) -1
-      && elf_i386_hash_entry(h)->tls_type != GOT_TLS_GD
+      && ! GOT_TLS_GD_ANY_P (elf_i386_hash_entry(h)->tls_type)
       && (elf_i386_hash_entry(h)->tls_type & GOT_TLS_IE) == 0)
     {
       Elf_Internal_Rela rel;
@@ -3555,6 +3906,7 @@
 #define elf_backend_reloc_type_class	      elf_i386_reloc_type_class
 #define elf_backend_relocate_section	      elf_i386_relocate_section
 #define elf_backend_size_dynamic_sections     elf_i386_size_dynamic_sections
+#define elf_backend_always_size_sections      elf_i386_always_size_sections
 #define elf_backend_plt_sym_val		      elf_i386_plt_sym_val
 
 #include "elf32-target.h"
Index: bfd/elf64-x86-64.c
===================================================================
--- bfd/elf64-x86-64.c.orig	2006-01-13 18:13:26.000000000 -0500
+++ bfd/elf64-x86-64.c	2006-01-13 18:14:55.000000000 -0500
@@ -112,12 +112,31 @@
   HOWTO(R_X86_64_GOTPC32, 0, 2, 32, TRUE, 0, complain_overflow_signed,
 	bfd_elf_generic_reloc, "R_X86_64_GOTPC32",
 	FALSE, 0xffffffff, 0xffffffff, TRUE),
+  EMPTY_HOWTO (27),
+  EMPTY_HOWTO (28),
+  EMPTY_HOWTO (29),
+  EMPTY_HOWTO (30),
+  EMPTY_HOWTO (31),
+  EMPTY_HOWTO (32),
+  EMPTY_HOWTO (33),
+  HOWTO(R_X86_64_GOTPC32_TLSDESC, 0, 2, 32, TRUE, 0,
+	complain_overflow_bitfield, bfd_elf_generic_reloc,
+	"R_X86_64_GOTPC32_TLSDESC",
+	FALSE, 0xffffffff, 0xffffffff, TRUE),
+  HOWTO(R_X86_64_TLSDESC_CALL, 0, 0, 0, FALSE, 0,
+	complain_overflow_dont, bfd_elf_generic_reloc,
+	"R_X86_64_TLSDESC_CALL",
+	FALSE, 0, 0, FALSE),
+  HOWTO(R_X86_64_TLSDESC, 0, 4, 64, FALSE, 0,
+	complain_overflow_bitfield, bfd_elf_generic_reloc,
+	"R_X86_64_TLSDESC",
+	FALSE, MINUS_ONE, MINUS_ONE, FALSE),
 
   /* We have a gap in the reloc numbers here.
      R_X86_64_standard counts the number up to this point, and
      R_X86_64_vt_offset is the value to subtract from a reloc type of
      R_X86_64_GNU_VT* to form an index into this table.  */
-#define R_X86_64_standard (R_X86_64_GOTPC32 + 1)
+#define R_X86_64_standard (R_X86_64_TLSDESC + 1)
 #define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard)
 
 /* GNU extension to record C++ vtable hierarchy.  */
@@ -166,14 +185,38 @@
   { BFD_RELOC_64_PCREL,		R_X86_64_PC64, },
   { BFD_RELOC_X86_64_GOTOFF64,	R_X86_64_GOTOFF64, },
   { BFD_RELOC_X86_64_GOTPC32,	R_X86_64_GOTPC32, },
+  { BFD_RELOC_X86_64_GOTPC32_TLSDESC, R_X86_64_GOTPC32_TLSDESC, },
+  { BFD_RELOC_X86_64_TLSDESC_CALL, R_X86_64_TLSDESC_CALL, },
+  { BFD_RELOC_X86_64_TLSDESC,	R_X86_64_TLSDESC, },
   { BFD_RELOC_VTABLE_INHERIT,	R_X86_64_GNU_VTINHERIT, },
   { BFD_RELOC_VTABLE_ENTRY,	R_X86_64_GNU_VTENTRY, },
 };
 
+static reloc_howto_type *
+elf64_x86_64_rtype_to_howto (bfd *abfd, unsigned r_type)
+{
+  unsigned i;
+
+  if (r_type < (unsigned int) R_X86_64_GNU_VTINHERIT
+      || r_type >= (unsigned int) R_X86_64_max)
+    {
+      if (r_type >= (unsigned int) R_X86_64_standard)
+	{
+	  (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
+				 abfd, (int) r_type);
+	  r_type = R_X86_64_NONE;
+	}
+      i = r_type;
+    }
+  else
+    i = r_type - (unsigned int) R_X86_64_vt_offset;
+  BFD_ASSERT (x86_64_elf_howto_table[i].type == r_type);
+  return &x86_64_elf_howto_table[i];
+}
 
 /* Given a BFD reloc type, return a HOWTO structure.  */
 static reloc_howto_type *
-elf64_x86_64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+elf64_x86_64_reloc_type_lookup (bfd *abfd,
 				bfd_reloc_code_real_type code)
 {
   unsigned int i;
@@ -182,7 +225,8 @@
        i++)
     {
       if (x86_64_reloc_map[i].bfd_reloc_val == code)
-	return &x86_64_elf_howto_table[i];
+	return elf64_x86_64_rtype_to_howto (abfd,
+					    x86_64_reloc_map[i].elf_reloc_val);
     }
   return 0;
 }
@@ -193,23 +237,10 @@
 elf64_x86_64_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
 			    Elf_Internal_Rela *dst)
 {
-  unsigned r_type, i;
+  unsigned r_type;
 
   r_type = ELF64_R_TYPE (dst->r_info);
-  if (r_type < (unsigned int) R_X86_64_GNU_VTINHERIT
-      || r_type >= (unsigned int) R_X86_64_max)
-    {
-      if (r_type >= (unsigned int) R_X86_64_standard)
-	{
-	  (*_bfd_error_handler) (_("%B: invalid relocation type %d"),
-				 abfd, (int) r_type);
-	  r_type = R_X86_64_NONE;
-	}
-      i = r_type;
-    }
-  else
-    i = r_type - (unsigned int) R_X86_64_vt_offset;
-  cache_ptr->howto = &x86_64_elf_howto_table[i];
+  cache_ptr->howto = elf64_x86_64_rtype_to_howto (abfd, r_type);
   BFD_ASSERT (r_type == cache_ptr->howto->type);
 }
 \f
@@ -353,7 +384,20 @@
 #define GOT_NORMAL	1
 #define GOT_TLS_GD	2
 #define GOT_TLS_IE	3
+#define GOT_TLS_GDESC	4
+#define GOT_TLS_GD_BOTH_P(type) \
+  ((type) == (GOT_TLS_GD | GOT_TLS_GDESC))
+#define GOT_TLS_GD_P(type) \
+  ((type) == GOT_TLS_GD || GOT_TLS_GD_BOTH_P (type))
+#define GOT_TLS_GDESC_P(type) \
+  ((type) == GOT_TLS_GDESC || GOT_TLS_GD_BOTH_P (type))
+#define GOT_TLS_GD_ANY_P(type) \
+  (GOT_TLS_GD_P (type) || GOT_TLS_GDESC_P (type))
   unsigned char tls_type;
+
+  /* Offset of the GOTPLT entry reserved for the TLS descriptor,
+     starting at the end of the jump table.  */
+  bfd_vma tlsdesc_got;
 };
 
 #define elf64_x86_64_hash_entry(ent) \
@@ -365,6 +409,9 @@
 
   /* tls_type for each local got entry.  */
   char *local_got_tls_type;
+
+  /* GOTPLT entries for TLS descriptors.  */
+  bfd_vma *local_tlsdesc_gotent;
 };
 
 #define elf64_x86_64_tdata(abfd) \
@@ -373,6 +420,8 @@
 #define elf64_x86_64_local_got_tls_type(abfd) \
   (elf64_x86_64_tdata (abfd)->local_got_tls_type)
 
+#define elf64_x86_64_local_tlsdesc_gotent(abfd) \
+  (elf64_x86_64_tdata (abfd)->local_tlsdesc_gotent)
 
 /* x86-64 ELF linker hash table.  */
 
@@ -389,11 +438,23 @@
   asection *sdynbss;
   asection *srelbss;
 
+  /* The offset into splt of the PLT entry for the TLS descriptor
+     resolver.  Special values are 0, if not necessary (or not found
+     to be necessary yet), and -1 if needed but not determined
+     yet.  */
+  bfd_vma tlsdesc_plt;
+  /* The offset into sgot of the GOT entry used by the PLT entry
+     above.  */
+  bfd_vma tlsdesc_got;
+
   union {
     bfd_signed_vma refcount;
     bfd_vma offset;
   } tls_ld_got;
 
+  /* The amount of space used by the jump slots in the GOT.  */
+  bfd_vma sgotplt_jump_table_size;
+
   /* Small local sym to section mapping cache.  */
   struct sym_sec_cache sym_sec;
 };
@@ -403,6 +464,9 @@
 #define elf64_x86_64_hash_table(p) \
   ((struct elf64_x86_64_link_hash_table *) ((p)->hash))
 
+#define elf64_x86_64_compute_jump_table_size(htab) \
+  ((htab)->srelplt->reloc_count * GOT_ENTRY_SIZE)
+
 /* Create an entry in an x86-64 ELF linker hash table.	*/
 
 static struct bfd_hash_entry *
@@ -428,6 +492,7 @@
       eh = (struct elf64_x86_64_link_hash_entry *) entry;
       eh->dyn_relocs = NULL;
       eh->tls_type = GOT_UNKNOWN;
+      eh->tlsdesc_got = (bfd_vma) -1;
     }
 
   return entry;
@@ -459,7 +524,10 @@
   ret->sdynbss = NULL;
   ret->srelbss = NULL;
   ret->sym_sec.abfd = NULL;
+  ret->tlsdesc_plt = 0;
+  ret->tlsdesc_got = 0;
   ret->tls_ld_got.refcount = 0;
+  ret->sgotplt_jump_table_size = 0;
 
   return &ret->elf.root;
 }
@@ -616,6 +684,8 @@
   switch (r_type)
     {
     case R_X86_64_TLSGD:
+    case R_X86_64_GOTPC32_TLSDESC:
+    case R_X86_64_TLSDESC_CALL:
     case R_X86_64_GOTTPOFF:
       if (is_local)
 	return R_X86_64_TPOFF32;
@@ -706,6 +776,8 @@
 	case R_X86_64_GOT32:
 	case R_X86_64_GOTPCREL:
 	case R_X86_64_TLSGD:
+	case R_X86_64_GOTPC32_TLSDESC:
+	case R_X86_64_TLSDESC_CALL:
 	  /* This symbol requires a global offset table entry.	*/
 	  {
 	    int tls_type, old_tls_type;
@@ -715,6 +787,9 @@
 	      default: tls_type = GOT_NORMAL; break;
 	      case R_X86_64_TLSGD: tls_type = GOT_TLS_GD; break;
 	      case R_X86_64_GOTTPOFF: tls_type = GOT_TLS_IE; break;
+	      case R_X86_64_GOTPC32_TLSDESC:
+	      case R_X86_64_TLSDESC_CALL:
+		tls_type = GOT_TLS_GDESC; break;
 	      }
 
 	    if (h != NULL)
@@ -733,14 +808,17 @@
 		    bfd_size_type size;
 
 		    size = symtab_hdr->sh_info;
-		    size *= sizeof (bfd_signed_vma) + sizeof (char);
+		    size *= sizeof (bfd_signed_vma)
+		      + sizeof (bfd_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;
+		    elf64_x86_64_local_tlsdesc_gotent (abfd)
+		      = (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info);
 		    elf64_x86_64_local_got_tls_type (abfd)
-		      = (char *) (local_got_refcounts + symtab_hdr->sh_info);
+		      = (char *) (local_got_refcounts + 2 * symtab_hdr->sh_info);
 		  }
 		local_got_refcounts[r_symndx] += 1;
 		old_tls_type
@@ -750,10 +828,14 @@
 	    /* 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))
+		&& (! GOT_TLS_GD_ANY_P (old_tls_type)
+		    || tls_type != GOT_TLS_IE))
 	      {
-		if (old_tls_type == GOT_TLS_IE && tls_type == GOT_TLS_GD)
+		if (old_tls_type == GOT_TLS_IE && GOT_TLS_GD_ANY_P (tls_type))
 		  tls_type = old_tls_type;
+		else if (GOT_TLS_GD_ANY_P (old_tls_type)
+			 && GOT_TLS_GD_ANY_P (tls_type))
+		  tls_type |= old_tls_type;
 		else
 		  {
 		    (*_bfd_error_handler)
@@ -1101,6 +1183,8 @@
 	  break;
 
 	case R_X86_64_TLSGD:
+	case R_X86_64_GOTPC32_TLSDESC:
+	case R_X86_64_TLSDESC_CALL:
 	case R_X86_64_GOTTPOFF:
 	case R_X86_64_GOT32:
 	case R_X86_64_GOTPCREL:
@@ -1368,6 +1452,7 @@
 
 	  /* We also need to make an entry in the .rela.plt section.  */
 	  htab->srelplt->size += sizeof (Elf64_External_Rela);
+	  htab->srelplt->reloc_count++;
 	}
       else
 	{
@@ -1381,6 +1466,9 @@
       h->needs_plt = 0;
     }
 
+  eh = (struct elf64_x86_64_link_hash_entry *) h;
+  eh->tlsdesc_got = (bfd_vma) -1;
+
   /* If R_X86_64_GOTTPOFF symbol is now local to the binary,
      make it a R_X86_64_TPOFF32 requiring no GOT entry.  */
   if (h->got.refcount > 0
@@ -1403,31 +1491,46 @@
 	    return FALSE;
 	}
 
-      s = htab->sgot;
-      h->got.offset = s->size;
-      s->size += GOT_ENTRY_SIZE;
-      /* R_X86_64_TLSGD needs 2 consecutive GOT slots.  */
-      if (tls_type == GOT_TLS_GD)
-	s->size += GOT_ENTRY_SIZE;
+      if (GOT_TLS_GDESC_P (tls_type))
+	{
+	  eh->tlsdesc_got = htab->sgotplt->size
+	    - elf64_x86_64_compute_jump_table_size (htab);
+	  htab->sgotplt->size += 2 * GOT_ENTRY_SIZE;
+	  h->got.offset = (bfd_vma) -2;
+	}
+      if (! GOT_TLS_GDESC_P (tls_type)
+	  || GOT_TLS_GD_P (tls_type))
+	{
+	  s = htab->sgot;
+	  h->got.offset = s->size;
+	  s->size += GOT_ENTRY_SIZE;
+	  if (GOT_TLS_GD_P (tls_type))
+	    s->size += GOT_ENTRY_SIZE;
+	}
       dyn = htab->elf.dynamic_sections_created;
       /* R_X86_64_TLSGD needs one dynamic relocation if local symbol
 	 and two if global.
 	 R_X86_64_GOTTPOFF needs one dynamic relocation.  */
-      if ((tls_type == GOT_TLS_GD && h->dynindx == -1)
+      if ((GOT_TLS_GD_P (tls_type) && h->dynindx == -1)
 	  || tls_type == GOT_TLS_IE)
 	htab->srelgot->size += sizeof (Elf64_External_Rela);
-      else if (tls_type == GOT_TLS_GD)
+      else if (GOT_TLS_GD_P (tls_type))
 	htab->srelgot->size += 2 * sizeof (Elf64_External_Rela);
-      else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-		|| h->root.type != bfd_link_hash_undefweak)
+      else if (! GOT_TLS_GDESC_P (tls_type)
+	       && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+		   || h->root.type != bfd_link_hash_undefweak)
 	       && (info->shared
 		   || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
 	htab->srelgot->size += sizeof (Elf64_External_Rela);
+      if (GOT_TLS_GDESC_P (tls_type))
+	{
+	  htab->srelplt->size += sizeof (Elf64_External_Rela);
+	  htab->tlsdesc_plt = (bfd_vma) -1;
+	}
     }
   else
     h->got.offset = (bfd_vma) -1;
 
-  eh = (struct elf64_x86_64_link_hash_entry *) h;
   if (eh->dyn_relocs == NULL)
     return TRUE;
 
@@ -1575,6 +1678,7 @@
       bfd_signed_vma *local_got;
       bfd_signed_vma *end_local_got;
       char *local_tls_type;
+      bfd_vma *local_tlsdesc_gotent;
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
       asection *srel;
@@ -1618,20 +1722,43 @@
       locsymcount = symtab_hdr->sh_info;
       end_local_got = local_got + locsymcount;
       local_tls_type = elf64_x86_64_local_got_tls_type (ibfd);
+      local_tlsdesc_gotent = elf64_x86_64_local_tlsdesc_gotent (ibfd);
       s = htab->sgot;
       srel = htab->srelgot;
-      for (; local_got < end_local_got; ++local_got, ++local_tls_type)
+      for (; local_got < end_local_got;
+	   ++local_got, ++local_tls_type, ++local_tlsdesc_gotent)
 	{
+	  *local_tlsdesc_gotent = (bfd_vma) -1;
 	  if (*local_got > 0)
 	    {
-	      *local_got = s->size;
-	      s->size += GOT_ENTRY_SIZE;
-	      if (*local_tls_type == GOT_TLS_GD)
-		s->size += GOT_ENTRY_SIZE;
+	      if (GOT_TLS_GDESC_P (*local_tls_type))
+		{
+		  *local_tlsdesc_gotent = htab->sgotplt->size
+		    - elf64_x86_64_compute_jump_table_size (htab);
+		  htab->sgotplt->size += 2 * GOT_ENTRY_SIZE;
+		  *local_got = (bfd_vma) -2;
+		}
+	      if (! GOT_TLS_GDESC_P (*local_tls_type)
+		  || GOT_TLS_GD_P (*local_tls_type))
+		{
+		  *local_got = s->size;
+		  s->size += GOT_ENTRY_SIZE;
+		  if (GOT_TLS_GD_P (*local_tls_type))
+		    s->size += GOT_ENTRY_SIZE;
+		}
 	      if (info->shared
-		  || *local_tls_type == GOT_TLS_GD
+		  || GOT_TLS_GD_ANY_P (*local_tls_type)
 		  || *local_tls_type == GOT_TLS_IE)
-		srel->size += sizeof (Elf64_External_Rela);
+		{
+		  if (GOT_TLS_GDESC_P (*local_tls_type))
+		    {
+		      htab->srelplt->size += sizeof (Elf64_External_Rela);
+		      htab->tlsdesc_plt = (bfd_vma) -1;
+		    }
+		  if (! GOT_TLS_GDESC_P (*local_tls_type)
+		      || GOT_TLS_GD_P (*local_tls_type))
+		    srel->size += sizeof (Elf64_External_Rela);
+		}
 	    }
 	  else
 	    *local_got = (bfd_vma) -1;
@@ -1653,6 +1780,34 @@
      sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
 
+  /* For every jump slot reserved in the sgotplt, reloc_count is
+     incremented.  However, when we reserve space for TLS descriptors,
+     it's not incremented, so in order to compute the space reserved
+     for them, it suffices to multiply the reloc count by the jump
+     slot size.  */
+  if (htab->srelplt)
+    htab->sgotplt_jump_table_size
+      = elf64_x86_64_compute_jump_table_size (htab);
+
+  if (htab->tlsdesc_plt)
+    {
+      /* If we're not using lazy TLS relocations, don't generate the
+	 PLT and GOT entries they require.  */
+      if ((info->flags & DF_BIND_NOW))
+	htab->tlsdesc_plt = 0;
+      else
+	{
+	  htab->tlsdesc_got = htab->sgot->size;
+	  htab->sgot->size += GOT_ENTRY_SIZE;
+	  /* Reserve room for the initial entry.
+	     FIXME: we could probably do away with it in this case.  */
+	  if (htab->splt->size == 0)
+	    htab->splt->size += PLT_ENTRY_SIZE;
+	  htab->tlsdesc_plt = htab->splt->size;
+	  htab->splt->size += PLT_ENTRY_SIZE;
+	}
+    }
+
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
   relocs = FALSE;
@@ -1676,7 +1831,8 @@
 
 	  /* We use the reloc_count field as a counter if we need
 	     to copy relocs into the output file.  */
-	  s->reloc_count = 0;
+	  if (s != htab->srelplt)
+	    s->reloc_count = 0;
 	}
       else
 	{
@@ -1736,6 +1892,11 @@
 	      || !add_dynamic_entry (DT_PLTREL, DT_RELA)
 	      || !add_dynamic_entry (DT_JMPREL, 0))
 	    return FALSE;
+
+	  if (htab->tlsdesc_plt
+	      && (!add_dynamic_entry (DT_TLSDESC_PLT, 0)
+		  || !add_dynamic_entry (DT_TLSDESC_GOT, 0)))
+	    return FALSE;
 	}
 
       if (relocs)
@@ -1763,6 +1924,41 @@
   return TRUE;
 }
 
+static bfd_boolean
+elf64_x86_64_always_size_sections (bfd *output_bfd,
+				   struct bfd_link_info *info)
+{
+  asection *tls_sec = elf_hash_table (info)->tls_sec;
+
+  if (tls_sec)
+    {
+      struct elf_link_hash_entry *tlsbase;
+
+      tlsbase = elf_link_hash_lookup (elf_hash_table (info),
+				      "_TLS_MODULE_BASE_",
+				      FALSE, FALSE, FALSE);
+
+      if (tlsbase && tlsbase->type == STT_TLS)
+	{
+	  struct bfd_link_hash_entry *bh = NULL;
+	  const struct elf_backend_data *bed
+	    = get_elf_backend_data (output_bfd);
+
+	  if (!(_bfd_generic_link_add_one_symbol
+		(info, output_bfd, "_TLS_MODULE_BASE_", BSF_LOCAL,
+		 tls_sec, 0, NULL, FALSE,
+		 bed->collect, &bh)))
+	    return FALSE;
+	  tlsbase = (struct elf_link_hash_entry *)bh;
+	  tlsbase->def_regular = 1;
+	  tlsbase->other = STV_HIDDEN;
+	  (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE);
+	}
+    }
+
+  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.  */
@@ -1821,6 +2017,7 @@
   Elf_Internal_Shdr *symtab_hdr;
   struct elf_link_hash_entry **sym_hashes;
   bfd_vma *local_got_offsets;
+  bfd_vma *local_tlsdesc_gotents;
   Elf_Internal_Rela *rel;
   Elf_Internal_Rela *relend;
 
@@ -1831,6 +2028,7 @@
   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (input_bfd);
   local_got_offsets = elf_local_got_offsets (input_bfd);
+  local_tlsdesc_gotents = elf64_x86_64_local_tlsdesc_gotent (input_bfd);
 
   rel = relocs;
   relend = relocs + input_section->reloc_count;
@@ -1842,7 +2040,7 @@
       struct elf_link_hash_entry *h;
       Elf_Internal_Sym *sym;
       asection *sec;
-      bfd_vma off;
+      bfd_vma off, offplt;
       bfd_vma relocation;
       bfd_boolean unresolved_reloc;
       bfd_reloc_status_type r;
@@ -2201,6 +2399,8 @@
 	  break;
 
 	case R_X86_64_TLSGD:
+	case R_X86_64_GOTPC32_TLSDESC:
+	case R_X86_64_TLSDESC_CALL:
 	case R_X86_64_GOTTPOFF:
 	  r_type = elf64_x86_64_tls_transition (info, r_type, h == NULL);
 	  tls_type = GOT_UNKNOWN;
@@ -2212,7 +2412,9 @@
 	      if (!info->shared && h->dynindx == -1 && tls_type == GOT_TLS_IE)
 		r_type = R_X86_64_TPOFF32;
 	    }
-	  if (r_type == R_X86_64_TLSGD)
+	  if (r_type == R_X86_64_TLSGD
+	      || r_type == R_X86_64_GOTPC32_TLSDESC
+	      || r_type == R_X86_64_TLSDESC_CALL)
 	    {
 	      if (tls_type == GOT_TLS_IE)
 		r_type = R_X86_64_GOTTPOFF;
@@ -2254,6 +2456,67 @@
 		  rel++;
 		  continue;
 		}
+	      else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC)
+		{
+		  /* GDesc -> LE transition.
+		     It's originally something like:
+		     leaq x@tlsdesc(%rip), %rax
+
+		     Change it to:
+		     movl $x@tpoff, %rax
+
+		     Registers other than %rax may be set up here.  */
+
+		  unsigned int val, type, type2;
+		  bfd_vma roff;
+
+		  /* First, make sure it's a leaq adding rip to a
+		     32-bit offset into any register, although it's
+		     probably almost always going to be rax.  */
+		  roff = rel->r_offset;
+		  BFD_ASSERT (roff >= 3);
+		  type = bfd_get_8 (input_bfd, contents + roff - 3);
+		  BFD_ASSERT ((type & 0xfb) == 0x48);
+		  type2 = bfd_get_8 (input_bfd, contents + roff - 2);
+		  BFD_ASSERT (type2 == 0x8d);
+		  val = bfd_get_8 (input_bfd, contents + roff - 1);
+		  BFD_ASSERT ((val & 0xc7) == 0x05);
+		  BFD_ASSERT (roff + 4 <= input_section->size);
+
+		  /* Now modify the instruction as appropriate.  */
+		  bfd_put_8 (output_bfd, 0x48 | ((type >> 2) & 1),
+			     contents + roff - 3);
+		  bfd_put_8 (output_bfd, 0xc7, contents + roff - 2);
+		  bfd_put_8 (output_bfd, 0xc0 | ((val >> 3) & 7),
+			     contents + roff - 1);
+		  bfd_put_32 (output_bfd, tpoff (info, relocation),
+			      contents + roff);
+		  continue;
+		}
+	      else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSDESC_CALL)
+		{
+		  /* GDesc -> LE transition.
+		     It's originally:
+		     call *(%rax)
+		     Turn it into:
+		     nop; nop.  */
+
+		  unsigned int val, type;
+		  bfd_vma roff;
+
+		  /* First, make sure it's a call *(%rax).  */
+		  roff = rel->r_offset;
+		  BFD_ASSERT (roff + 2 <= input_section->size);
+		  type = bfd_get_8 (input_bfd, contents + roff);
+		  BFD_ASSERT (type == 0xff);
+		  val = bfd_get_8 (input_bfd, contents + roff + 1);
+		  BFD_ASSERT (val == 0x10);
+
+		  /* Now modify the instruction as appropriate.  */
+		  bfd_put_8 (output_bfd, 0x90, contents + roff);
+		  bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
+		  continue;
+		}
 	      else
 		{
 		  unsigned int val, type, reg;
@@ -2319,13 +2582,17 @@
 	    abort ();
 
 	  if (h != NULL)
-	    off = h->got.offset;
+	    {
+	      off = h->got.offset;
+	      offplt = elf64_x86_64_hash_entry (h)->tlsdesc_got;
+	    }
 	  else
 	    {
 	      if (local_got_offsets == NULL)
 		abort ();
 
 	      off = local_got_offsets[r_symndx];
+	      offplt = local_tlsdesc_gotents[r_symndx];
 	    }
 
 	  if ((off & 1) != 0)
@@ -2335,30 +2602,61 @@
 	      Elf_Internal_Rela outrel;
 	      bfd_byte *loc;
 	      int dr_type, indx;
+	      asection *sreloc;
 
 	      if (htab->srelgot == NULL)
 		abort ();
 
+	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
+
+	      if (GOT_TLS_GDESC_P (tls_type))
+		{
+		  outrel.r_info = ELF64_R_INFO (indx, R_X86_64_TLSDESC);
+		  BFD_ASSERT (htab->sgotplt_jump_table_size + offplt
+			      + 2 * GOT_ENTRY_SIZE <= htab->sgotplt->size);
+		  outrel.r_offset = (htab->sgotplt->output_section->vma
+				     + htab->sgotplt->output_offset
+				     + offplt
+				     + htab->sgotplt_jump_table_size);
+		  sreloc = htab->srelplt;
+		  loc = sreloc->contents;
+		  loc += sreloc->reloc_count++
+		    * sizeof (Elf64_External_Rela);
+		  BFD_ASSERT (loc + sizeof (Elf64_External_Rela)
+			      <= sreloc->contents + sreloc->size);
+		  if (indx == 0)
+		    outrel.r_addend = relocation - dtpoff_base (info);
+		  else
+		    outrel.r_addend = 0;
+		  bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
+		}
+
+	      sreloc = htab->srelgot;
+
 	      outrel.r_offset = (htab->sgot->output_section->vma
 				 + htab->sgot->output_offset + off);
 
-	      indx = h && h->dynindx != -1 ? h->dynindx : 0;
-	      if (r_type == R_X86_64_TLSGD)
+	      if (GOT_TLS_GD_P (tls_type))
 		dr_type = R_X86_64_DTPMOD64;
+	      else if (GOT_TLS_GDESC_P (tls_type))
+		goto dr_done;
 	      else
 		dr_type = R_X86_64_TPOFF64;
 
 	      bfd_put_64 (output_bfd, 0, htab->sgot->contents + off);
 	      outrel.r_addend = 0;
-	      if (dr_type == R_X86_64_TPOFF64 && indx == 0)
+	      if ((dr_type == R_X86_64_TPOFF64
+		   || dr_type == R_X86_64_TLSDESC) && indx == 0)
 		outrel.r_addend = relocation - dtpoff_base (info);
 	      outrel.r_info = ELF64_R_INFO (indx, dr_type);
 
-	      loc = htab->srelgot->contents;
-	      loc += htab->srelgot->reloc_count++ * sizeof (Elf64_External_Rela);
+	      loc = sreloc->contents;
+	      loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela);
+	      BFD_ASSERT (loc + sizeof (Elf64_External_Rela)
+			  <= sreloc->contents + sreloc->size);
 	      bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
 
-	      if (r_type == R_X86_64_TLSGD)
+	      if (GOT_TLS_GD_P (tls_type))
 		{
 		  if (indx == 0)
 		    {
@@ -2374,27 +2672,37 @@
 		      outrel.r_info = ELF64_R_INFO (indx,
 						    R_X86_64_DTPOFF64);
 		      outrel.r_offset += GOT_ENTRY_SIZE;
-		      htab->srelgot->reloc_count++;
+		      sreloc->reloc_count++;
 		      loc += sizeof (Elf64_External_Rela);
+		      BFD_ASSERT (loc + sizeof (Elf64_External_Rela)
+				  <= sreloc->contents + sreloc->size);
 		      bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
 		    }
 		}
 
+	    dr_done:
 	      if (h != NULL)
 		h->got.offset |= 1;
 	      else
 		local_got_offsets[r_symndx] |= 1;
 	    }
 
-	  if (off >= (bfd_vma) -2)
+	  if (off >= (bfd_vma) -2
+	      && ! GOT_TLS_GDESC_P (tls_type))
 	    abort ();
 	  if (r_type == ELF64_R_TYPE (rel->r_info))
 	    {
-	      relocation = htab->sgot->output_section->vma
-			   + htab->sgot->output_offset + off;
+	      if (r_type == R_X86_64_GOTPC32_TLSDESC
+		  || r_type == R_X86_64_TLSDESC_CALL)
+		relocation = htab->sgotplt->output_section->vma
+		  + htab->sgotplt->output_offset
+		  + offplt + htab->sgotplt_jump_table_size;
+	      else
+		relocation = htab->sgot->output_section->vma
+		  + htab->sgot->output_offset + off;
 	      unresolved_reloc = FALSE;
 	    }
-	  else
+	  else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSGD)
 	    {
 	      unsigned int i;
 	      static unsigned char tlsgd[8]
@@ -2434,6 +2742,77 @@
 	      rel++;
 	      continue;
 	    }
+	  else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC)
+	    {
+	      /* GDesc -> IE transition.
+		 It's originally something like:
+		 leaq x@tlsdesc(%rip), %rax
+
+		 Change it to:
+		 movq x@gottpoff(%rip), %rax # before nop; nop
+
+		 Registers other than %rax may be set up here.  */
+
+	      unsigned int val, type, type2;
+	      bfd_vma roff;
+
+	      /* First, make sure it's a leaq adding rip to a 32-bit
+		 offset into any register, although it's probably
+		 almost always going to be rax.  */
+	      roff = rel->r_offset;
+	      BFD_ASSERT (roff >= 3);
+	      type = bfd_get_8 (input_bfd, contents + roff - 3);
+	      BFD_ASSERT ((type & 0xfb) == 0x48);
+	      type2 = bfd_get_8 (input_bfd, contents + roff - 2);
+	      BFD_ASSERT (type2 == 0x8d);
+	      val = bfd_get_8 (input_bfd, contents + roff - 1);
+	      BFD_ASSERT ((val & 0xc7) == 0x05);
+	      BFD_ASSERT (roff + 4 <= input_section->size);
+
+	      /* Now modify the instruction as appropriate.  */
+	      /* To turn a leaq into a movq in the form we use it, it
+		 suffices to change the second byte from 0x8d to
+		 0x8b.  */
+	      bfd_put_8 (output_bfd, 0x8b, contents + roff - 2);
+
+	      bfd_put_32 (output_bfd,
+			  htab->sgot->output_section->vma
+			  + htab->sgot->output_offset + off
+			  - rel->r_offset
+			  - input_section->output_section->vma
+			  - input_section->output_offset
+			  - 4,
+			  contents + roff);
+	      continue;
+	    }
+	  else if (ELF64_R_TYPE (rel->r_info) == R_X86_64_TLSDESC_CALL)
+	    {
+	      /* GDesc -> IE transition.
+		 It's originally:
+		 call *(%rax)
+
+		 Change it to:
+		 nop; nop.  */
+
+	      unsigned int val, type;
+	      bfd_vma roff;
+
+	      /* First, make sure it's a call *(%eax).  */
+	      roff = rel->r_offset;
+	      BFD_ASSERT (roff + 2 <= input_section->size);
+	      type = bfd_get_8 (input_bfd, contents + roff);
+	      BFD_ASSERT (type == 0xff);
+	      val = bfd_get_8 (input_bfd, contents + roff + 1);
+	      BFD_ASSERT (val == 0x10);
+
+	      /* Now modify the instruction as appropriate.  */
+	      bfd_put_8 (output_bfd, 0x90, contents + roff);
+	      bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
+
+	      continue;
+	    }
+	  else
+	    BFD_ASSERT (FALSE);
 	  break;
 
 	case R_X86_64_TLSLD:
@@ -2672,7 +3051,7 @@
     }
 
   if (h->got.offset != (bfd_vma) -1
-      && elf64_x86_64_hash_entry (h)->tls_type != GOT_TLS_GD
+      && ! GOT_TLS_GD_ANY_P (elf64_x86_64_hash_entry (h)->tls_type)
       && elf64_x86_64_hash_entry (h)->tls_type != GOT_TLS_IE)
     {
       Elf_Internal_Rela rela;
@@ -2827,6 +3206,18 @@
 		  dyn.d_un.d_val -= s->size;
 		}
 	      break;
+
+	    case DT_TLSDESC_PLT:
+	      s = htab->splt;
+	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
+		+ htab->tlsdesc_plt;
+	      break;
+
+	    case DT_TLSDESC_GOT:
+	      s = htab->sgot;
+	      dyn.d_un.d_ptr = s->output_section->vma + s->output_offset
+		+ htab->tlsdesc_got;
+	      break;
 	    }
 
 	  bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
@@ -2861,6 +3252,40 @@
 
 	  elf_section_data (htab->splt->output_section)->this_hdr.sh_entsize =
 	    PLT_ENTRY_SIZE;
+
+	  if (htab->tlsdesc_plt)
+	    {
+	      bfd_put_64 (output_bfd, (bfd_vma) 0,
+			  htab->sgot->contents + htab->tlsdesc_got);
+
+	      memcpy (htab->splt->contents + htab->tlsdesc_plt,
+		      elf64_x86_64_plt0_entry,
+		      PLT_ENTRY_SIZE);
+
+	      /* Add offset for pushq GOT+8(%rip), since the
+		 instruction uses 6 bytes subtract this value.  */
+	      bfd_put_32 (output_bfd,
+			  (htab->sgotplt->output_section->vma
+			   + htab->sgotplt->output_offset
+			   + 8
+			   - htab->splt->output_section->vma
+			   - htab->splt->output_offset
+			   - htab->tlsdesc_plt
+			   - 6),
+			  htab->splt->contents + htab->tlsdesc_plt + 2);
+	      /* Add offset for jmp *GOT+TDG(%rip), where TGD stands for
+		 htab->tlsdesc_got. The 12 is the offset to the end of
+		 the instruction.  */
+	      bfd_put_32 (output_bfd,
+			  (htab->sgot->output_section->vma
+			   + htab->sgot->output_offset
+			   + htab->tlsdesc_got
+			   - htab->splt->output_section->vma
+			   - htab->splt->output_offset
+			   - htab->tlsdesc_plt
+			   - 12),
+			  htab->splt->contents + htab->tlsdesc_plt + 8);
+	    }
 	}
     }
 
@@ -3132,6 +3557,7 @@
 #define elf_backend_reloc_type_class	    elf64_x86_64_reloc_type_class
 #define elf_backend_relocate_section	    elf64_x86_64_relocate_section
 #define elf_backend_size_dynamic_sections   elf64_x86_64_size_dynamic_sections
+#define elf_backend_always_size_sections    elf64_x86_64_always_size_sections
 #define elf_backend_plt_sym_val		    elf64_x86_64_plt_sym_val
 #define elf_backend_object_p		    elf64_x86_64_elf_object_p
 #define bfd_elf64_mkobject		    elf64_x86_64_mkobject
Index: bfd/libbfd.h
===================================================================
--- bfd/libbfd.h.orig	2006-01-13 18:13:26.000000000 -0500
+++ bfd/libbfd.h	2006-01-13 18:14:55.000000000 -0500
@@ -1034,6 +1034,9 @@
   "BFD_RELOC_386_TLS_DTPMOD32",
   "BFD_RELOC_386_TLS_DTPOFF32",
   "BFD_RELOC_386_TLS_TPOFF32",
+  "BFD_RELOC_386_TLS_GOTDESC",
+  "BFD_RELOC_386_TLS_DESC_CALL",
+  "BFD_RELOC_386_TLS_DESC",
   "BFD_RELOC_X86_64_GOT32",
   "BFD_RELOC_X86_64_PLT32",
   "BFD_RELOC_X86_64_COPY",
@@ -1052,6 +1055,9 @@
   "BFD_RELOC_X86_64_TPOFF32",
   "BFD_RELOC_X86_64_GOTOFF64",
   "BFD_RELOC_X86_64_GOTPC32",
+  "BFD_RELOC_X86_64_GOTPC32_TLSDESC",
+  "BFD_RELOC_X86_64_TLSDESC_CALL",
+  "BFD_RELOC_X86_64_TLSDESC",
   "BFD_RELOC_NS32K_IMM_8",
   "BFD_RELOC_NS32K_IMM_16",
   "BFD_RELOC_NS32K_IMM_32",
Index: bfd/reloc.c
===================================================================
--- bfd/reloc.c.orig	2006-01-13 18:13:26.000000000 -0500
+++ bfd/reloc.c	2006-01-13 18:14:55.000000000 -0500
@@ -2298,6 +2298,12 @@
   BFD_RELOC_386_TLS_DTPOFF32
 ENUMX
   BFD_RELOC_386_TLS_TPOFF32
+ENUMX
+  BFD_RELOC_386_TLS_GOTDESC
+ENUMX
+  BFD_RELOC_386_TLS_DESC_CALL
+ENUMX
+  BFD_RELOC_386_TLS_DESC
 ENUMDOC
   i386/elf relocations
 
@@ -2337,6 +2343,12 @@
   BFD_RELOC_X86_64_GOTOFF64
 ENUMX
   BFD_RELOC_X86_64_GOTPC32
+ENUMX
+  BFD_RELOC_X86_64_GOTPC32_TLSDESC
+ENUMX
+  BFD_RELOC_X86_64_TLSDESC_CALL
+ENUMX
+  BFD_RELOC_X86_64_TLSDESC
 ENUMDOC
   x86-64/elf relocations
 
Index: binutils/readelf.c
===================================================================
--- binutils/readelf.c.orig	2006-01-13 18:13:58.000000000 -0500
+++ binutils/readelf.c	2006-01-13 18:14:55.000000000 -0500
@@ -1480,6 +1480,8 @@
 
     case DT_VERSYM:	return "VERSYM";
 
+    case DT_TLSDESC_GOT: return "TLSDESC_GOT";
+    case DT_TLSDESC_PLT: return "TLSDESC_PLT";
     case DT_RELACOUNT:	return "RELACOUNT";
     case DT_RELCOUNT:	return "RELCOUNT";
     case DT_FLAGS_1:	return "FLAGS_1";
Index: gas/config/tc-i386.c
===================================================================
--- gas/config/tc-i386.c.orig	2006-01-13 18:13:26.000000000 -0500
+++ gas/config/tc-i386.c	2006-01-13 18:14:55.000000000 -0500
@@ -1345,6 +1345,8 @@
       || fixP->fx_r_type == BFD_RELOC_386_TLS_GOTIE
       || 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_386_TLS_GOTDESC
+      || fixP->fx_r_type == BFD_RELOC_386_TLS_DESC_CALL
       || 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
@@ -1356,6 +1358,8 @@
       || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF32
       || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF64
       || fixP->fx_r_type == BFD_RELOC_X86_64_GOTOFF64
+      || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPC32_TLSDESC
+      || fixP->fx_r_type == BFD_RELOC_X86_64_TLSDESC_CALL
       || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
     return 0;
@@ -2196,7 +2200,14 @@
 		&& fits_in_signed_byte (disp))
 	      i.types[op] |= Disp8;
 	  }
-	else
+	else if (i.reloc[op] == BFD_RELOC_386_TLS_DESC_CALL
+		 || i.reloc[op] == BFD_RELOC_X86_64_TLSDESC_CALL)
+	  {
+	    fix_new_exp (frag_now, frag_more (0) - frag_now->fr_literal, 0,
+			 i.op[op].disps, 0, i.reloc[op]);
+	    i.types[op] &= ~Disp;
+	  }
+ 	else
 	  /* We only support 64bit displacement on constants.  */
 	  i.types[op] &= ~Disp64;
       }
@@ -3157,7 +3168,13 @@
 		  if ((i.index_reg->reg_flags & RegRex) != 0)
 		    i.rex |= REX_EXTY;
 		}
-	      i.rm.mode = mode_from_disp_size (i.types[op]);
+
+	      if (i.disp_operands
+		  && (i.reloc[op] == BFD_RELOC_386_TLS_DESC_CALL
+		      || i.reloc[op] == BFD_RELOC_X86_64_TLSDESC_CALL))
+		i.rm.mode = 0;
+	      else
+		i.rm.mode = mode_from_disp_size (i.types[op]);
 	    }
 
 	  if (fake_zero_displacement)
@@ -3856,7 +3873,9 @@
     { "DTPOFF",   { BFD_RELOC_386_TLS_LDO_32, BFD_RELOC_X86_64_DTPOFF32 }, Imm32|Imm32S|Imm64|Disp32|Disp64 },
     { "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE,  0                         }, 0 },
     { "INDNTPOFF",{ BFD_RELOC_386_TLS_IE,     0                         }, 0 },
-    { "GOT",      { BFD_RELOC_386_GOT32,      BFD_RELOC_X86_64_GOT32    }, Imm32|Imm32S|Disp32 }
+    { "GOT",      { BFD_RELOC_386_GOT32,      BFD_RELOC_X86_64_GOT32    }, Imm32|Imm32S|Disp32 },
+    { "TLSDESC",  { BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_X86_64_GOTPC32_TLSDESC }, Imm32|Imm32S|Disp32 },
+    { "TLSCALL",  { BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_X86_64_TLSDESC_CALL }, Imm32|Imm32S|Disp32 }
   };
   char *cp;
   unsigned int j;
@@ -5063,9 +5082,11 @@
       case BFD_RELOC_386_TLS_IE_32:
       case BFD_RELOC_386_TLS_IE:
       case BFD_RELOC_386_TLS_GOTIE:
+      case BFD_RELOC_386_TLS_GOTDESC:
       case BFD_RELOC_X86_64_TLSGD:
       case BFD_RELOC_X86_64_TLSLD:
       case BFD_RELOC_X86_64_GOTTPOFF:
+      case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
 	value = 0; /* Fully resolved at runtime.  No addend.  */
 	/* Fallthrough */
       case BFD_RELOC_386_TLS_LE:
@@ -5078,6 +5099,13 @@
 	S_SET_THREAD_LOCAL (fixP->fx_addsy);
 	break;
 
+      case BFD_RELOC_386_TLS_DESC_CALL:
+      case BFD_RELOC_X86_64_TLSDESC_CALL:
+	value = 0; /* Fully resolved at runtime.  No addend.  */
+	S_SET_THREAD_LOCAL (fixP->fx_addsy);
+	fixP->fx_done = 0;
+	return;
+
       case BFD_RELOC_386_GOT32:
       case BFD_RELOC_X86_64_GOT32:
 	value = 0; /* Fully resolved at runtime.  No addend.  */
@@ -5655,6 +5683,8 @@
     case BFD_RELOC_386_TLS_GOTIE:
     case BFD_RELOC_386_TLS_LE_32:
     case BFD_RELOC_386_TLS_LE:
+    case BFD_RELOC_386_TLS_GOTDESC:
+    case BFD_RELOC_386_TLS_DESC_CALL:
     case BFD_RELOC_X86_64_TLSGD:
     case BFD_RELOC_X86_64_TLSLD:
     case BFD_RELOC_X86_64_DTPOFF32:
@@ -5664,6 +5694,8 @@
     case BFD_RELOC_X86_64_TPOFF64:
     case BFD_RELOC_X86_64_GOTOFF64:
     case BFD_RELOC_X86_64_GOTPC32:
+    case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
+    case BFD_RELOC_X86_64_TLSDESC_CALL:
     case BFD_RELOC_RVA:
     case BFD_RELOC_VTABLE_ENTRY:
     case BFD_RELOC_VTABLE_INHERIT:
@@ -5760,6 +5792,8 @@
 	  case BFD_RELOC_X86_64_TLSGD:
 	  case BFD_RELOC_X86_64_TLSLD:
 	  case BFD_RELOC_X86_64_GOTTPOFF:
+	  case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
+	  case BFD_RELOC_X86_64_TLSDESC_CALL:
 	    rel->addend = fixp->fx_offset - fixp->fx_size;
 	    break;
 	  default:
Index: include/elf/common.h
===================================================================
--- include/elf/common.h.orig	2006-01-13 18:14:01.000000000 -0500
+++ include/elf/common.h	2006-01-13 18:14:55.000000000 -0500
@@ -576,6 +576,8 @@
 #define DT_VALRNGHI	0x6ffffdff
 
 #define DT_ADDRRNGLO	0x6ffffe00
+#define DT_TLSDESC_PLT	0x6ffffef6
+#define DT_TLSDESC_GOT	0x6ffffef7
 #define DT_GNU_CONFLICT	0x6ffffef8
 #define DT_GNU_LIBLIST	0x6ffffef9
 #define DT_CONFIG	0x6ffffefa
Index: include/elf/i386.h
===================================================================
--- include/elf/i386.h.orig	2006-01-13 18:13:26.000000000 -0500
+++ include/elf/i386.h	2006-01-13 18:14:55.000000000 -0500
@@ -1,5 +1,5 @@
 /* ix86 ELF support for BFD.
-   Copyright 1998, 1999, 2000, 2002, 2004 Free Software Foundation, Inc.
+   Copyright 1998, 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -61,6 +61,10 @@
      RELOC_NUMBER (R_386_TLS_DTPMOD32, 35)
      RELOC_NUMBER (R_386_TLS_DTPOFF32, 36)
      RELOC_NUMBER (R_386_TLS_TPOFF32,  37)
+/* 38 */
+     RELOC_NUMBER (R_386_TLS_GOTDESC,  39)
+     RELOC_NUMBER (R_386_TLS_DESC_CALL,40)
+     RELOC_NUMBER (R_386_TLS_DESC,     41)
 
      /* Used by Intel.  */
      RELOC_NUMBER (R_386_USED_BY_INTEL_200, 200)
Index: include/elf/x86-64.h
===================================================================
--- include/elf/x86-64.h.orig	2006-01-13 18:13:26.000000000 -0500
+++ include/elf/x86-64.h	2006-01-13 18:14:55.000000000 -0500
@@ -1,5 +1,5 @@
 /* x86_64 ELF support for BFD.
-   Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
    Contributed by Jan Hubicka <jh@suse.cz>
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -53,6 +53,14 @@
      RELOC_NUMBER (R_X86_64_GOTOFF64, 25)     /* 64 bit offset to GOT */
      RELOC_NUMBER (R_X86_64_GOTPC32,  26)     /* 32 bit signed pc relative
                                                  offset to GOT */
+     /* 27 .. 33 */
+     RELOC_NUMBER (R_X86_64_GOTPC32_TLSDESC, 34)
+					      /* 32 bit signed pc relative
+						 offset to TLS descriptor
+						 in the GOT.  */
+     RELOC_NUMBER (R_X86_64_TLSDESC_CALL, 35) /* Relaxable call through TLS
+						 descriptor.  */
+     RELOC_NUMBER (R_X86_64_TLSDESC, 36)      /* 2x64-bit TLS descriptor.  */
      RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250)       /* GNU C++ hack  */
      RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251)         /* GNU C++ hack  */
 END_RELOC_NUMBERS (R_X86_64_max)
Index: ld/testsuite/ld-i386/i386.exp
===================================================================
--- ld/testsuite/ld-i386/i386.exp.orig	2006-01-13 18:13:26.000000000 -0500
+++ ld/testsuite/ld-i386/i386.exp	2006-01-13 18:14:55.000000000 -0500
@@ -1,5 +1,5 @@
 # Expect script for ld-i386 tests
-#   Copyright (C) 2002 Free Software Foundation
+#   Copyright (C) 2002, 2005 Free Software Foundation
 #
 # This file is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -22,7 +22,9 @@
 if { !([istarget "i?86-*-elf*"]		
        || ([istarget "i?86-*-linux*"]
 	   && ![istarget "*-*-*aout*"]
-	   && ![istarget "*-*-*oldld*"])) } {
+	   && ![istarget "*-*-*oldld*"])
+       || [istarget "x86_64-*-linux*"]
+       || [istarget "amd64-*-linux*"]) } {
     return
 }
 
@@ -41,6 +43,11 @@
      {{readelf -Ssrl tlspic.rd} {objdump -drj.text tlspic.dd}
       {objdump -sj.got tlspic.sd} {objdump -sj.tdata tlspic.td}}
       "libtlspic.so"}
+    {"TLS descriptor -fpic -shared transitions" "-shared -melf_i386"
+     "--32" {tlsdesc.s tlspic2.s}
+     {{readelf -Ssrl tlsdesc.rd} {objdump -drj.text tlsdesc.dd}
+      {objdump "-s -j.got -j.got.plt" tlsdesc.sd} {objdump -sj.tdata tlsdesc.td}}
+      "libtlsdesc.so"}
     {"Helper shared library" "-shared -melf_i386"
      "--32" {tlslib.s} {} "libtlslib.so"}
     {"TLS -fpic and -fno-pic exec transitions"
@@ -48,10 +55,19 @@
      {{readelf -Ssrl tlsbin.rd} {objdump -drj.text tlsbin.dd}
       {objdump -sj.got tlsbin.sd} {objdump -sj.tdata tlsbin.td}}
       "tlsbin"}
+    {"TLS descriptor -fpic and -fno-pic exec transitions"
+     "-melf_i386 tmpdir/libtlslib.so" "--32" {tlsbindesc.s tlsbin.s}
+     {{readelf -Ssrl tlsbindesc.rd} {objdump -drj.text tlsbindesc.dd}
+      {objdump -sj.got tlsbindesc.sd} {objdump -sj.tdata tlsbindesc.td}}
+      "tlsbindesc"}
     {"TLS -fno-pic -shared" "-shared -melf_i386"
      "--32" {tlsnopic1.s tlsnopic2.s}
      {{readelf -Ssrl tlsnopic.rd} {objdump -drj.text tlsnopic.dd}
       {objdump -sj.got tlsnopic.sd}} "libtlsnopic.so"}
+    {"TLS with global dynamic and descriptors"
+	"-shared -melf_i386" "--32" {tlsgdesc.s}
+     {{readelf -Ssrl tlsgdesc.rd} {objdump -drj.text tlsgdesc.dd}}
+      "libtlsgdesc.so"}
     {"TLS in debug sections" "-melf_i386"
      "--32" {tlsg.s}
      {{objdump -sj.debug_foobar tlsg.sd}} "tlsg"}
Index: ld/testsuite/ld-i386/pcrel16.d
===================================================================
--- ld/testsuite/ld-i386/pcrel16.d.orig	2006-01-13 18:13:26.000000000 -0500
+++ ld/testsuite/ld-i386/pcrel16.d	2006-01-13 18:14:55.000000000 -0500
@@ -1,5 +1,6 @@
 #name: PCREL16 overflow
-#ld: -Ttext 0x0
+#as: --32
+#ld: -melf_i386 -Ttext 0x0
 #objdump: -drj.text -m i8086
 
 .*: +file format elf32-i386
Index: ld/testsuite/ld-i386/pcrel8.d
===================================================================
--- ld/testsuite/ld-i386/pcrel8.d.orig	2006-01-13 18:13:26.000000000 -0500
+++ ld/testsuite/ld-i386/pcrel8.d	2006-01-13 18:14:55.000000000 -0500
@@ -1,3 +1,4 @@
 #name: PCREL8 overflow
-#ld:
+#as: --32
+#ld: -melf_i386
 #error: .*relocation truncated to fit: R_386_PC8 .*
Index: ld/testsuite/ld-i386/tlsbindesc.dd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-i386/tlsbindesc.dd	2006-01-14 12:49:47.000000000 -0500
@@ -0,0 +1,463 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --32
+#ld: -melf_i386 tmpdir/libtlslib.so
+#objdump: -drj.text
+#target: i?86-*-*
+
+# PT_TLS layout is:
+# Offset from	Offset from	Name
+# TCB base	TCB end
+# 0x00		-0xa0		sg1..sg8
+# 0x20		-0x80		sl1..sl8
+# 0x40		-0x60		sh1..sh8
+# 0x60		-0x40		bg1..bg8
+# 0x80		-0x20		bl1..bl8
+
+.*: +file format elf32-i386
+
+Disassembly of section .text:
+
+[0-9a-f]+ <fn2>:
+ [0-9a-f]+:	55[ 	]+push   %ebp
+ [0-9a-f]+:	89 e5[ 	]+mov    %esp,%ebp
+ [0-9a-f]+:	53[ 	]+push   %ebx
+ [0-9a-f]+:	50[ 	]+push   %eax
+ [0-9a-f]+:	e8 00 00 00 00[ 	]+call   [0-9a-f]+ <fn2\+0xa>
+ [0-9a-f]+:	5b[ 	]+pop    %ebx
+ [0-9a-f]+:	81 c3 fa 10 00 00[ 	]+add    \$0x10fa,%ebx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable
+ [0-9a-f]+:	8b 83 f8 ff ff ff[ 	]+mov    0xfffffff8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG1
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable where
+#  the variable is referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 e8 ff ff ff[ 	]+mov    0xffffffe8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable where
+#  the variable is referenced through @gotntpoff too
+ [0-9a-f]+:	8b 83 dc ff ff ff[ 	]+mov    0xffffffdc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable where
+#  the variable is referenced through @gottpoff and @gotntpoff too
+ [0-9a-f]+:	8b 83 f0 ff ff ff[ 	]+mov    0xfffffff0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with global variable defined in executable
+ [0-9a-f]+:	8d 05 00 f0 ff ff[ 	]+lea    0xfffff000,%eax
+#							sg1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with local variable defined in executable
+ [0-9a-f]+:	8d 05 20 f0 ff ff[ 	]+lea    0xfffff020,%eax
+#							sl1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with hidden variable defined in executable
+ [0-9a-f]+:	8d 05 40 f0 ff ff[ 	]+lea    0xfffff040,%eax
+#							sh1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD -> LE
+ [0-9a-f]+:	8d 05 00 f0 ff ff[ 	]+lea    0xfffff000,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 90 20 f0 ff ff[ 	]+lea    0xfffff020\(%eax\),%edx
+#							sl1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 24 f0 ff ff[ 	]+lea    0xfffff024\(%eax\),%ecx
+#							sl2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD -> LE against hidden variables
+ [0-9a-f]+:	8d 05 00 f0 ff ff[ 	]+lea    0xfffff000,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 90 40 f0 ff ff[ 	]+lea    0xfffff040\(%eax\),%edx
+#							sh1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 44 f0 ff ff[ 	]+lea    0xfffff044\(%eax\),%ecx
+#							sh2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b e8 ff ff ff[ 	]+sub    0xffffffe8\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	sG2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 ec ff ff ff[ 	]+sub    0xffffffec\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b dc ff ff ff[ 	]+add    0xffffffdc\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sG3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 f0 ff ff ff[ 	]+add    0xfffffff0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against global var defined in exec
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 e9 00 10 00 00[ 	]+sub    \$0x1000,%ecx
+#							sg1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE -> LE against local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c0 20 f0 ff ff[ 	]+add    \$0xfffff020,%eax
+#							sl1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against hidden var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 e9 c0 0f 00 00[ 	]+sub    \$0xfc0,%ecx
+#							sh1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  Direct access through %gs
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	8b 8b e0 ff ff ff[ 	]+mov    0xffffffe0\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sG5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 11[ 	]+mov    %gs:\(%ecx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE->LE against local var
+ [0-9a-f]+:	c7 c0 30 f0 ff ff[ 	]+mov    \$0xfffff030,%eax
+#							sl5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 10[ 	]+mov    %gs:\(%eax\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE->LE against hidden var
+ [0-9a-f]+:	c7 c2 50 f0 ff ff[ 	]+mov    \$0xfffff050,%edx
+#							sh5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 12[ 	]+mov    %gs:\(%edx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 5d fc[ 	]+mov    0xfffffffc\(%ebp\),%ebx
+ [0-9a-f]+:	c9[ 	]+leave *
+ [0-9a-f]+:	c3[ 	]+ret *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+
+[0-9a-f]+ <_start>:
+ [0-9a-f]+:	55[ 	]+push   %ebp
+ [0-9a-f]+:	89 e5[ 	]+mov    %esp,%ebp
+ [0-9a-f]+:	e8 00 00 00 00[ 	]+call   [0-9a-f]+ <_start\+0x8>
+ [0-9a-f]+:	59[ 	]+pop    %ecx
+ [0-9a-f]+:	81 c1 a4 0f 00 00[ 	]+add    \$0xfa4,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 91 f4 ff ff ff[ 	]+sub    0xfffffff4\(%ecx\),%edx
+#				->R_386_TLS_TPOFF32	sG6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 05 e8 a0 04 08[ 	]+add    0x804a0e8,%eax
+#				->R_386_TLS_TPOFF	sG7
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff direct %gs access IE against global var
+ [0-9a-f]+:	8b 15 00 a1 04 08[ 	]+mov    0x804a100,%edx
+#				->R_386_TLS_TPOFF	sG8
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 02[ 	]+mov    %gs:\(%edx\),%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against global var defined in exec
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 ea 8c 0f 00 00[ 	]+sub    \$0xf8c,%edx
+#							bg6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff IE -> LE against global var defined in exec
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c0 78 f0 ff ff[ 	]+add    \$0xfffff078,%eax
+#							bg7
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff direct %gs access IE -> LE against global var defined
+#  in exec
+ [0-9a-f]+:	c7 c2 7c f0 ff ff[ 	]+mov    \$0xfffff07c,%edx
+#							bg8
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 02[ 	]+mov    %gs:\(%edx\),%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against local var
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 ea 6c 0f 00 00[ 	]+sub    \$0xf6c,%edx
+#							bl6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff IE -> LE against local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c0 98 f0 ff ff[ 	]+add    \$0xfffff098,%eax
+#							bl7
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff direct %gs access IE -> LE against local var
+ [0-9a-f]+:	c7 c2 9c f0 ff ff[ 	]+mov    \$0xfffff09c,%edx
+#							bl8
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 02[ 	]+mov    %gs:\(%edx\),%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE -> LE against hidden but not local var
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 ea ac 0f 00 00[ 	]+sub    \$0xfac,%edx
+#							sh6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff IE -> LE against hidden but not local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c0 58 f0 ff ff[ 	]+add    \$0xfffff058,%eax
+#							sh7
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @indntpoff direct %gs access IE -> LE against hidden but not
+#  local var
+ [0-9a-f]+:	c7 c2 5c f0 ff ff[ 	]+mov    \$0xfffff05c,%edx
+#							sh8
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 02[ 	]+mov    %gs:\(%edx\),%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @tpoff, global var defined in exec
+ [0-9a-f]+:	ba 00 10 00 00[ 	]+mov    \$0x1000,%edx
+#							sg1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	29 d0[ 	]+sub    %edx,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @tpoff, local var
+ [0-9a-f]+:	b8 7f 0f 00 00[ 	]+mov    \$0xf7f,%eax
+#							bl1+1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	29 c2[ 	]+sub    %eax,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @tpoff, hidden var defined in exec
+ [0-9a-f]+:	b8 bd 0f 00 00[ 	]+mov    \$0xfbd,%eax
+#							sh1+3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	29 c2[ 	]+sub    %eax,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, global var defined in exec
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 90 04 f0 ff ff[ 	]+lea    0xfffff004\(%eax\),%edx
+#							sg2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, local var, non-canonical sequence
+ [0-9a-f]+:	b8 86 f0 ff ff[ 	]+mov    \$0xfffff086,%eax
+#							bl2+2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	01 c2[ 	]+add    %eax,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, hidden var defined in exec, non-canonical sequence
+ [0-9a-f]+:	65 8b 15 00 00 00 00[ 	]+mov    %gs:0x0,%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	81 c2 45 f0 ff ff[ 	]+add    \$0xfffff045,%edx
+#							sh2+1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, global var defined in exec
+ [0-9a-f]+:	65 a1 08 f0 ff ff[ 	]+mov    %gs:0xfffff008,%eax
+#							sg3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, local var
+ [0-9a-f]+:	65 8b 15 8b f0 ff ff[ 	]+mov    %gs:0xfffff08b,%edx
+#							bl3+3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LE @ntpoff, hidden var defined in exec
+ [0-9a-f]+:	65 8b 15 49 f0 ff ff[ 	]+mov    %gs:0xfffff049,%edx
+#							sh3+1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 5d fc[ 	]+mov    0xfffffffc\(%ebp\),%ebx
+ [0-9a-f]+:	c9[ 	]+leave *
+ [0-9a-f]+:	c3[ 	]+ret *
Index: ld/testsuite/ld-i386/tlsbindesc.rd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-i386/tlsbindesc.rd	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,154 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --32
+#ld: -melf_i386 tmpdir/libtlslib.so
+#readelf: -Ssrl
+#target: i?86-*-*
+
+There are 15 section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+  \[ 1\] \.interp +.*
+  \[ 2\] \.hash +.*
+  \[ 3\] \.dynsym +.*
+  \[ 4\] \.dynstr +.*
+  \[ 5\] \.rel.dyn +.*
+  \[ 6\] \.text +PROGBITS +0+8049000 .*
+  \[ 7\] \.tdata +PROGBITS +0+804a000 [0-9a-f]+ 000060 00 WAT  0   0 4096
+  \[ 8\] \.tbss +NOBITS +[0-9a-f]+ [0-9a-f]+ 000040 00 WAT  0   0  1
+  \[ 9\] \.dynamic +DYNAMIC +0+804a060 .*
+  \[10\] \.got +PROGBITS +0+804a0e0 .*
+  \[11\] \.got\.plt +PROGBITS +0+804a104 .*
+  \[12\] \.shstrtab +.*
+  \[13\] \.symtab +.*
+  \[14\] \.strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x8049158
+There are 6 program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  PHDR.*
+  INTERP.*
+.*Requesting program interpreter.*
+  LOAD.*
+  LOAD.*
+  DYNAMIC.*
+  TLS +0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x0+60 0x0+a0 R +0x1000
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +
+   01 +.interp *
+   02 +.interp .hash .dynsym .dynstr .rel.dyn .text *
+   03 +.tdata .dynamic .got .got.plt *
+   04 +.dynamic *
+   05 +.tdata .tbss *
+
+Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 9 entries:
+ Offset +Info +Type +Sym.Value +Sym. Name
+0+804a0e0  0000010e R_386_TLS_TPOFF +0+ +sG3
+0+804a0e4  0000020e R_386_TLS_TPOFF +0+ +sG5
+0+804a0e8  0000030e R_386_TLS_TPOFF +0+ +sG7
+0+804a0ec  00000425 R_386_TLS_TPOFF32 0+ +sG2
+0+804a0f0  00000525 R_386_TLS_TPOFF32 0+ +sG4
+0+804a0f4  0000050e R_386_TLS_TPOFF +0+ +sG4
+0+804a0f8  00000725 R_386_TLS_TPOFF32 0+ +sG6
+0+804a0fc  00000825 R_386_TLS_TPOFF32 0+ +sG1
+0+804a100  00000b0e R_386_TLS_TPOFF +0+ +sG8
+
+Symbol table '.dynsym' contains 12 entries:
+ +Num: +Value  Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG7
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG8
+
+Symbol table '.symtab' contains 71 entries:
+ +Num: +Value  Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +[0-9]+: 00000020 +0 TLS +LOCAL  DEFAULT +7 sl1
+ +[0-9]+: 00000024 +0 TLS +LOCAL  DEFAULT +7 sl2
+ +[0-9]+: 00000028 +0 TLS +LOCAL  DEFAULT +7 sl3
+ +[0-9]+: 0000002c +0 TLS +LOCAL  DEFAULT +7 sl4
+ +[0-9]+: 00000030 +0 TLS +LOCAL  DEFAULT +7 sl5
+ +[0-9]+: 00000034 +0 TLS +LOCAL  DEFAULT +7 sl6
+ +[0-9]+: 00000038 +0 TLS +LOCAL  DEFAULT +7 sl7
+ +[0-9]+: 0000003c +0 TLS +LOCAL  DEFAULT +7 sl8
+ +[0-9]+: 00000080 +0 TLS +LOCAL  DEFAULT +8 bl1
+ +[0-9]+: 00000084 +0 TLS +LOCAL  DEFAULT +8 bl2
+ +[0-9]+: 00000088 +0 TLS +LOCAL  DEFAULT +8 bl3
+ +[0-9]+: 0000008c +0 TLS +LOCAL  DEFAULT +8 bl4
+ +[0-9]+: 00000090 +0 TLS +LOCAL  DEFAULT +8 bl5
+ +[0-9]+: 00000094 +0 TLS +LOCAL  DEFAULT +8 bl6
+ +[0-9]+: 00000098 +0 TLS +LOCAL  DEFAULT +8 bl7
+ +[0-9]+: 0000009c +0 TLS +LOCAL  DEFAULT +8 bl8
+ +[0-9]+: 00000000 +0 TLS +LOCAL  HIDDEN +7 _TLS_MODULE_BASE_
+ +[0-9]+: 0+804a060 +0 OBJECT  LOCAL  HIDDEN    9 _DYNAMIC
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN   11 _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0000001c +0 TLS +GLOBAL DEFAULT +7 sg8
+ +[0-9]+: 0000007c +0 TLS +GLOBAL DEFAULT +8 bg8
+ +[0-9]+: 00000074 +0 TLS +GLOBAL DEFAULT +8 bg6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 00000068 +0 TLS +GLOBAL DEFAULT +8 bg3
+ +[0-9]+: 00000008 +0 TLS +GLOBAL DEFAULT +7 sg3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG7
+ +[0-9]+: 00000048 +0 TLS +GLOBAL HIDDEN +7 sh3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0000000c +0 TLS +GLOBAL DEFAULT +7 sg4
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: 00000010 +0 TLS +GLOBAL DEFAULT +7 sg5
+ +[0-9]+: 00000070 +0 TLS +GLOBAL DEFAULT +8 bg5
+ +[0-9]+: 00000058 +0 TLS +GLOBAL HIDDEN +7 sh7
+ +[0-9]+: 0000005c +0 TLS +GLOBAL HIDDEN +7 sh8
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1
+ +[0-9]+: 0+8049158 +0 FUNC +GLOBAL DEFAULT +6 _start
+ +[0-9]+: 0000004c +0 TLS +GLOBAL HIDDEN +7 sh4
+ +[0-9]+: 00000078 +0 TLS +GLOBAL DEFAULT +8 bg7
+ +[0-9]+: 00000050 +0 TLS +GLOBAL HIDDEN +7 sh5
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: 0+8049000 +0 FUNC +GLOBAL DEFAULT +6 fn2
+ +[0-9]+: 00000004 +0 TLS +GLOBAL DEFAULT +7 sg2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: 00000040 +0 TLS +GLOBAL HIDDEN +7 sh1
+ +[0-9]+: 00000014 +0 TLS +GLOBAL DEFAULT +7 sg6
+ +[0-9]+: 00000018 +0 TLS +GLOBAL DEFAULT +7 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 00000044 +0 TLS +GLOBAL HIDDEN +7 sh2
+ +[0-9]+: 00000054 +0 TLS +GLOBAL HIDDEN +7 sh6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG8
+ +[0-9]+: 00000064 +0 TLS +GLOBAL DEFAULT +8 bg2
+ +[0-9]+: 00000060 +0 TLS +GLOBAL DEFAULT +8 bg1
+ +[0-9]+: 0000006c +0 TLS +GLOBAL DEFAULT +8 bg4
Index: ld/testsuite/ld-i386/tlsbindesc.s
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-i386/tlsbindesc.s	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,167 @@
+	/* Force .got aligned to 4K, so it very likely gets at 0x804a100
+	   (0x60 bytes .tdata and 0xa0 bytes .dynamic)  */
+	.section ".tdata", "awT", @progbits
+	.balign	4096
+	.globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8
+	.globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+	.hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	/* Force .text aligned to 4K, so it very likely gets at 0x8049000.  */
+	.text
+	.balign	4096
+	.globl	fn2
+	.type	fn2,@function
+fn2:
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	pushl	%eax
+	call	1f
+1:	popl	%ebx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable */
+	leal	sG1@tlsdesc(%ebx), %eax
+	call	*sG1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through @gottpoff too */
+	leal	sG2@tlsdesc(%ebx), %eax
+	call	*sG2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through @gotntpoff too */
+	leal	sG3@tlsdesc(%ebx), %eax
+	call	*sG3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through @gottpoff and @gotntpoff too */
+	leal	sG4@tlsdesc(%ebx), %eax
+	call	*sG4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with global variable defined in executable */
+	leal	sg1@tlsdesc(%ebx), %eax
+	call	*sg1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with local variable defined in executable */
+	leal	sl1@tlsdesc(%ebx), %eax
+	call	*sl1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with hidden variable defined in executable */
+	leal	sh1@tlsdesc(%ebx), %eax
+	call	*sh1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* LD -> LE */
+	leal	_TLS_MODULE_BASE_@tlsdesc(%ebx), %eax
+	call	*_TLS_MODULE_BASE_@tlscall(%eax)
+	nop;nop
+	leal	sl1@dtpoff(%eax), %edx
+	nop;nop
+	leal	sl2@dtpoff(%eax), %ecx
+	nop;nop;nop;nop
+
+	/* LD -> LE against hidden variables */
+	leal	_TLS_MODULE_BASE_@tlsdesc(%ebx), %eax
+	call	*_TLS_MODULE_BASE_@tlscall(%eax)
+	nop;nop
+	leal	sh1@dtpoff(%eax), %edx
+	nop;nop
+	leal	sh2@dtpoff(%eax), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sG2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sG4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sG3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sG4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE -> LE against global var defined in exec */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sg1@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE -> LE against local var */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sl1@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE -> LE against hidden var */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sh1@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* Direct access through %gs  */
+
+	/* @gotntpoff IE against global var  */
+	movl	sG5@gotntpoff(%ebx), %ecx
+	nop;nop
+	movl	%gs:(%ecx), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE->LE against local var  */
+	movl	sl5@gotntpoff(%ebx), %eax
+	nop;nop
+	movl	%gs:(%eax), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE->LE against hidden var  */
+	movl	sh5@gotntpoff(%ebx), %edx
+	nop;nop
+	movl	%gs:(%edx), %edx
+	nop;nop;nop;nop
+
+	movl    -4(%ebp), %ebx
+	leave
+	ret
Index: ld/testsuite/ld-i386/tlsbindesc.sd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-i386/tlsbindesc.sd	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,13 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --32
+#ld: -melf_i386 tmpdir/libtlslib.so
+#objdump: -sj.got
+#target: i?86-*-*
+
+.*:     file format elf32-i386
+
+Contents of section \.got:
+ 804a0e0 [0-9a-f]+ 00000000 00000000 [0-9a-f]+  .*
+ 804a0f0 00000000 00000000 00000000 00000000  .*
+ 804a100 00000000  +.*
Index: ld/testsuite/ld-i386/tlsbindesc.td
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-i386/tlsbindesc.td	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,16 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --32
+#ld: -melf_i386 tmpdir/libtlslib.so
+#objdump: -sj.tdata
+#target: i?86-*-*
+
+.*:     file format elf32-i386
+
+Contents of section \.tdata:
+ 804a000 11000000 12000000 13000000 14000000  .*
+ 804a010 15000000 16000000 17000000 18000000  .*
+ 804a020 41000000 42000000 43000000 44000000  .*
+ 804a030 45000000 46000000 47000000 48000000  .*
+ 804a040 01010000 02010000 03010000 04010000  .*
+ 804a050 05010000 06010000 07010000 08010000  .*
Index: ld/testsuite/ld-i386/tlsdesc.dd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-i386/tlsdesc.dd	2006-01-14 12:45:03.000000000 -0500
@@ -0,0 +1,399 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --32
+#ld: -shared -melf_i386
+#objdump: -drj.text
+#target: i?86-*-*
+
+.*: +file format elf32-i386
+
+Disassembly of section .text:
+
+[0-9a-f]+ <fn1>:
+ [0-9a-f]+:	55[ 	]+push   %ebp
+ [0-9a-f]+:	89 e5[ 	]+mov    %esp,%ebp
+ [0-9a-f]+:	53[ 	]+push   %ebx
+ [0-9a-f]+:	50[ 	]+push   %eax
+ [0-9a-f]+:	e8 00 00 00 00[ 	]+call   [0-9a-f]+ <fn1\+0xa>
+ [0-9a-f]+:	5b[ 	]+pop    %ebx
+ [0-9a-f]+:	81 c3 9a 13 00 00[ 	]+add    \$0x[0-9a-f]+,%ebx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GDesc
+ [0-9a-f]+:	8d 83 24 00 00 00[ 	]+lea    0x24\(%ebx\),%eax
+#				->R_386_TLS_DESC	sg1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 f8 ff ff ff[ 	]+mov    0xfffffff8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sg2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gotntpoff too
+ [0-9a-f]+:	8b 83 c4 ff ff ff[ 	]+mov    0xffffffc4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sg3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gottpoff and
+ [0-9a-f]+:	8b 83 d4 ff ff ff[ 	]+mov    0xffffffd4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sg4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD against local variable
+ [0-9a-f]+:	8d 83 0c 00 00 00[ 	]+lea    0xc\(%ebx\),%eax
+#				->R_386_TLS_DESC	sl1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against local variable referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 b0 ff ff ff[ 	]+mov    0xffffffb0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sl2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against local variable referenced through @gotntpoff
+ [0-9a-f]+:	8b 83 b4 ff ff ff[ 	]+mov    0xffffffb4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sl3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against local variable referenced through @gottpoff and
+ [0-9a-f]+:	8b 83 bc ff ff ff[ 	]+mov    0xffffffbc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sl4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD against hidden and local variable
+ [0-9a-f]+:	8d 83 2c 00 00 00[ 	]+lea    0x2c\(%ebx\),%eax
+#				->R_386_TLS_DESC	sh1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden and local variable referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 fc ff ff ff[ 	]+mov    0xfffffffc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sh2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden and local variable referenced through @gotntpoff too
+ [0-9a-f]+:	8b 83 c8 ff ff ff[ 	]+mov    0xffffffc8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sh3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden and local variable referenced through @gottpoff and @gotntpoff too
+ [0-9a-f]+:	8b 83 e8 ff ff ff[ 	]+mov    0xffffffe8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sh4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD against hidden but not local variable
+ [0-9a-f]+:	8d 83 14 00 00 00[ 	]+lea    0x14\(%ebx\),%eax
+#				->R_386_TLS_DESC	sH1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden but not local variable referenced through
+ [0-9a-f]+:	8b 83 cc ff ff ff[ 	]+mov    0xffffffcc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sH2
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden but not local variable referenced through
+ [0-9a-f]+:	8b 83 ec ff ff ff[ 	]+mov    0xffffffec\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sH3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden but not local variable referenced through
+ [0-9a-f]+:	8b 83 e0 ff ff ff[ 	]+mov    0xffffffe0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sH4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD
+ [0-9a-f]+:	8d 83 1c 00 00 00[ 	]+lea    0x1c\(%ebx\),%eax
+#				->R_386_TLS_DESC	_TLS_MODULE_BASE_
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 90 20 00 00 00[ 	]+lea    0x20\(%eax\),%edx
+#							sl1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 26 00 00 00[ 	]+lea    0x26\(%eax\),%ecx
+#							sl2+2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD against hidden and local variables
+ [0-9a-f]+:	8d 90 40 00 00 00[ 	]+lea    0x40\(%eax\),%edx
+#							sh1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 47 00 00 00[ 	]+lea    0x47\(%eax\),%ecx
+#							sh2+3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  LD against hidden but not local variables
+ [0-9a-f]+:	8d 90 60 00 00 00[ 	]+lea    0x60\(%eax\),%edx
+#							sH1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 88 65 00 00 00[ 	]+lea    0x65\(%eax\),%ecx
+#							sH2+1
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b f8 ff ff ff[ 	]+sub    0xfffffff8\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	sg2
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 d0 ff ff ff[ 	]+sub    0xffffffd0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sg4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b c4 ff ff ff[ 	]+add    0xffffffc4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sg3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 d4 ff ff ff[ 	]+add    0xffffffd4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sg4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b b0 ff ff ff[ 	]+sub    0xffffffb0\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	[0xdcffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 b8 ff ff ff[ 	]+sub    0xffffffb8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	[0xd4ffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b b4 ff ff ff[ 	]+add    0xffffffb4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	[0x28000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 bc ff ff ff[ 	]+add    0xffffffbc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	[0x2c000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against hidden and local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b fc ff ff ff[ 	]+sub    0xfffffffc\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	[0xbcffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against hidden and local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 e4 ff ff ff[ 	]+sub    0xffffffe4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	[0xb4ffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden and local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b c8 ff ff ff[ 	]+add    0xffffffc8\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	[0x48000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden and local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 e8 ff ff ff[ 	]+add    0xffffffe8\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	[0x4c000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against hidden but not local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b cc ff ff ff[ 	]+sub    0xffffffcc\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	[0x9cffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against hidden but not local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 83 dc ff ff ff[ 	]+sub    0xffffffdc\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	[0x94ffffff]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden but not local var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b ec ff ff ff[ 	]+add    0xffffffec\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	[0x68000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden but not local var
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 83 e0 ff ff ff[ 	]+add    0xffffffe0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	[0x6c000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  Direct access through %gs
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	8b 8b d8 ff ff ff[ 	]+mov    0xffffffd8\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sg5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 11[ 	]+mov    %gs:\(%ecx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against local var
+ [0-9a-f]+:	8b 83 c0 ff ff ff[ 	]+mov    0xffffffc0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	[0x30000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 10[ 	]+mov    %gs:\(%eax\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden and local var
+ [0-9a-f]+:	8b 93 f0 ff ff ff[ 	]+mov    0xfffffff0\(%ebx\),%edx
+#				->R_386_TLS_TPOFF	[0x50000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 12[ 	]+mov    %gs:\(%edx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against hidden but not local var
+ [0-9a-f]+:	8b 8b f4 ff ff ff[ 	]+mov    0xfffffff4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	[0x70000000]
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 8b 11[ 	]+mov    %gs:\(%ecx\),%edx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 5d fc[ 	]+mov    0xfffffffc\(%ebp\),%ebx
+ [0-9a-f]+:	c9[ 	]+leave *
+ [0-9a-f]+:	c3[ 	]+ret *
Index: ld/testsuite/ld-i386/tlsdesc.rd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-i386/tlsdesc.rd	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,155 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --32
+#ld: -shared -melf_i386
+#readelf: -Ssrl
+#target: i?86-*-*
+
+There are [0-9]+ section headers, starting at offset 0x.*:
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+  \[ 1\] \.hash +.*
+  \[ 2\] \.dynsym +.*
+  \[ 3\] \.dynstr +.*
+  \[ 4\] \.rel.dyn +.*
+  \[ 5\] \.rel.plt +.*
+  \[ 6\] \.text +.*
+  \[ 7\] \.tdata +PROGBITS +[0-9a-f]+ [0-9a-f]+ 000060 00 WAT  0   0  1
+  \[ 8\] \.tbss +NOBITS +[0-9aa-f]+ [0-9a-f]+ 000020 00 WAT  0   0  1
+  \[ 9\] \.dynamic +.*
+  \[10\] \.got +.*
+  \[11\] \.got.plt +.*
+  \[12\] \.shstrtab +.*
+  \[13\] \.symtab +.*
+  \[14\] \.strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x[0-9a-f]+
+There are [0-9]+ program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  LOAD.*
+  LOAD.*
+  DYNAMIC.*
+  TLS +0x[0-9a-f]+ 0x[0-9a-f]+ 0x[0-9a-f]+ 0x0+60 0x0+80 R +0x1
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +.hash .dynsym .dynstr .rel.dyn .rel.plt .text *
+   01 +.tdata .dynamic .got .got.plt *
+   02 +.dynamic *
+   03 +.tdata .tbss *
+
+Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 20 entries:
+ Offset +Info +Type +Sym.Value +Sym. Name
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+0e R_386_TLS_TPOFF *
+[0-9a-f]+ +0+25 R_386_TLS_TPOFF32
+[0-9a-f]+ +0+50e R_386_TLS_TPOFF   0+8   sg3
+[0-9a-f]+ +0+625 R_386_TLS_TPOFF32 0+c   sg4
+[0-9a-f]+ +0+60e R_386_TLS_TPOFF   0+c   sg4
+[0-9a-f]+ +0+70e R_386_TLS_TPOFF   0+10   sg5
+[0-9a-f]+ +0+b25 R_386_TLS_TPOFF32 0+4   sg2
+
+Relocation section '.rel.plt' at offset 0x[0-9a-f]+ contains 5 entries:
+ Offset     Info    Type            Sym.Value  Sym. Name
+[0-9a-f]+ +0+829 R_386_TLS_DESC * 0+   sg1
+[0-9a-f]+ +0+29 R_386_TLS_DESC *
+[0-9a-f]+ +0+29 R_386_TLS_DESC *
+[0-9a-f]+ +0+29 R_386_TLS_DESC *
+[0-9a-f]+ +0+29 R_386_TLS_DESC *
+
+Symbol table '.dynsym' contains 16 entries:
+ +Num: + Value  Size Type + Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +7 sg8
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +7 sg3
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +7 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +7 sg5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +6 fn1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +7 sg2
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +7 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +7 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 54 entries:
+ +Num: +Value  Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +[0-9]+: 0+20 +0 TLS +LOCAL  DEFAULT +7 sl1
+ +[0-9]+: 0+24 +0 TLS +LOCAL  DEFAULT +7 sl2
+ +[0-9]+: 0+28 +0 TLS +LOCAL  DEFAULT +7 sl3
+ +[0-9]+: 0+2c +0 TLS +LOCAL  DEFAULT +7 sl4
+ +[0-9]+: 0+30 +0 TLS +LOCAL  DEFAULT +7 sl5
+ +[0-9]+: 0+34 +0 TLS +LOCAL  DEFAULT +7 sl6
+ +[0-9]+: 0+38 +0 TLS +LOCAL  DEFAULT +7 sl7
+ +[0-9]+: 0+3c +0 TLS +LOCAL  DEFAULT +7 sl8
+ +[0-9]+: 0+60 +0 TLS +LOCAL  HIDDEN +8 sH1
+ +[0-9]+: 0+ +0 TLS +LOCAL  HIDDEN +7 _TLS_MODULE_BASE_
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _DYNAMIC
+ +[0-9]+: 0+48 +0 TLS +LOCAL  HIDDEN +7 sh3
+ +[0-9]+: 0+64 +0 TLS +LOCAL  HIDDEN +8 sH2
+ +[0-9]+: 0+78 +0 TLS +LOCAL  HIDDEN +8 sH7
+ +[0-9]+: 0+58 +0 TLS +LOCAL  HIDDEN +7 sh7
+ +[0-9]+: 0+5c +0 TLS +LOCAL  HIDDEN +7 sh8
+ +[0-9]+: 0+6c +0 TLS +LOCAL  HIDDEN +8 sH4
+ +[0-9]+: 0+4c +0 TLS +LOCAL  HIDDEN +7 sh4
+ +[0-9]+: 0+68 +0 TLS +LOCAL  HIDDEN +8 sH3
+ +[0-9]+: 0+50 +0 TLS +LOCAL  HIDDEN +7 sh5
+ +[0-9]+: 0+70 +0 TLS +LOCAL  HIDDEN +8 sH5
+ +[0-9]+: 0+74 +0 TLS +LOCAL  HIDDEN +8 sH6
+ +[0-9]+: 0+7c +0 TLS +LOCAL  HIDDEN +8 sH8
+ +[0-9]+: 0+40 +0 TLS +LOCAL  HIDDEN +7 sh1
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+44 +0 TLS +LOCAL  HIDDEN +7 sh2
+ +[0-9]+: 0+54 +0 TLS +LOCAL  HIDDEN +7 sh6
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +7 sg8
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +7 sg3
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +7 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +7 sg5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +6 fn1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +7 sg2
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +7 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +7 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
Index: ld/testsuite/ld-i386/tlsdesc.s
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-i386/tlsdesc.s	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,276 @@
+	.section ".tdata", "awT", @progbits
+	.globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8
+	.globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+	.hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	.text
+	.globl	fn1
+	.type	fn1,@function
+fn1:
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	pushl	%eax
+	call	1f
+1:	popl	%ebx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sg1@tlsdesc(%ebx), %eax
+	call	*sg1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is referenced through @gottpoff too */
+	leal	sg2@tlsdesc(%ebx), %eax
+	call	*sg2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is referenced through @gotntpoff too */
+	leal	sg3@tlsdesc(%ebx), %eax
+	call	*sg3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is referenced through @gottpoff and
+	   @gotntpoff too */
+	leal	sg4@tlsdesc(%ebx), %eax
+	call	*sg4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD against local variable */
+	leal	sl1@tlsdesc(%ebx), %eax
+	call	*sl1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against local variable referenced through @gottpoff too */
+	leal	sl2@tlsdesc(%ebx), %eax
+	call	*sl2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against local variable referenced through @gotntpoff
+	   too */
+	leal	sl3@tlsdesc(%ebx), %eax
+	call	*sl3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against local variable referenced through @gottpoff and
+	   @gotntpoff too */
+	leal	sl4@tlsdesc(%ebx), %eax
+	call	*sl4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD against hidden and local variable */
+	leal	sh1@tlsdesc(%ebx), %eax
+	call	*sh1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden and local variable referenced through
+	   @gottpoff too */
+	leal	sh2@tlsdesc(%ebx), %eax
+	call	*sh2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden and local variable referenced through
+	   @gotntpoff too */
+	leal	sh3@tlsdesc(%ebx), %eax
+	call	*sh3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden and local variable referenced through
+	   @gottpoff and @gotntpoff too */
+	leal	sh4@tlsdesc(%ebx), %eax
+	call	*sh4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD against hidden but not local variable */
+	leal	sH1@tlsdesc(%ebx), %eax
+	call	*sH1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   @gottpoff too */
+	leal	sH2@tlsdesc(%ebx), %eax
+	call	*sH2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   @gotntpoff too */
+	leal	sH3@tlsdesc(%ebx), %eax
+	call	*sH3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   @gottpoff and @gotntpoff too */
+	leal	sH4@tlsdesc(%ebx), %eax
+	call	*sH4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* LD */
+	leal	_TLS_MODULE_BASE_@tlsdesc(%ebx), %eax
+	call	*_TLS_MODULE_BASE_@tlscall(%eax)
+	nop;nop
+	leal	sl1@dtpoff(%eax), %edx
+	nop;nop
+	leal	2+sl2@dtpoff(%eax), %ecx
+	nop;nop;nop;nop
+
+	/* LD against hidden and local variables */
+	leal	sh1@dtpoff(%eax), %edx
+	nop;nop
+	leal	sh2@dtpoff+3(%eax), %ecx
+	nop;nop;nop;nop
+
+	/* LD against hidden but not local variables */
+	leal	sH1@dtpoff(%eax), %edx
+	nop;nop
+	leal	sH2@dtpoff+1(%eax), %ecx
+	nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sg2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sg4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sg3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sg4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sl2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sl4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sl3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sl4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against hidden and local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sh2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against hidden and local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sh4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden and local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sh3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden and local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sh4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against hidden but not local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sH2@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against hidden but not local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	subl	sH4@gottpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden but not local var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sH3@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden but not local var  */
+	movl	%gs:0, %eax
+	nop;nop
+	addl	sH4@gotntpoff(%ebx), %eax
+	nop;nop;nop;nop
+
+	/* Direct access through %gs  */
+
+	/* @gotntpoff IE against global var  */
+	movl	sg5@gotntpoff(%ebx), %ecx
+	nop;nop
+	movl	%gs:(%ecx), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against local var  */
+	movl	sl5@gotntpoff(%ebx), %eax
+	nop;nop
+	movl	%gs:(%eax), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden and local var  */
+	movl	sh5@gotntpoff(%ebx), %edx
+	nop;nop
+	movl	%gs:(%edx), %edx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against hidden but not local var  */
+	movl	sH5@gotntpoff(%ebx), %ecx
+	nop;nop
+	movl	%gs:(%ecx), %edx
+	nop;nop;nop;nop
+
+	movl    -4(%ebp), %ebx
+	leave
+	ret
Index: ld/testsuite/ld-i386/tlsdesc.sd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-i386/tlsdesc.sd	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,20 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --32
+#ld: -shared -melf_i386
+#objdump: -s -j.got -j.got.plt
+#target: i?86-*-*
+
+.*:     file format elf32-i386
+
+Contents of section \.got:
+ [0-9a-f]+ dcffffff 28000000 d4ffffff 2c000000  .*
+ [0-9a-f]+ 30000000 00000000 48000000 9cffffff  .*
+ [0-9a-f]+ 00000000 00000000 00000000 94ffffff  .*
+ [0-9a-f]+ 6c000000 b4ffffff 4c000000 68000000  .*
+ [0-9a-f]+ 50000000 70000000 00000000 bcffffff  .*
+Contents of section \.got\.plt:
+ [0-9a-f]+ ec150000 00000000 00000000 00000000  .*
+ [0-9a-f]+ 20000000 00000000 60000000 00000000  .*
+ [0-9a-f]+ 00000000 00000000 00000000 00000000  .*
+ [0-9a-f]+ 40000000 +.*
Index: ld/testsuite/ld-i386/tlsdesc.td
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-i386/tlsdesc.td	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,16 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --32
+#ld: -shared -melf_i386
+#objdump: -sj.tdata
+#target: i?86-*-*
+
+.*:     file format elf32-i386
+
+Contents of section \.tdata:
+ [0-9a-f]+ 11000000 12000000 13000000 14000000  .*
+ [0-9a-f]+ 15000000 16000000 17000000 18000000  .*
+ [0-9a-f]+ 41000000 42000000 43000000 44000000  .*
+ [0-9a-f]+ 45000000 46000000 47000000 48000000  .*
+ [0-9a-f]+ 01010000 02010000 03010000 04010000  .*
+ [0-9a-f]+ 05010000 06010000 07010000 08010000  .*
Index: ld/testsuite/ld-i386/tlsgdesc.dd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-i386/tlsgdesc.dd	2006-01-14 12:45:53.000000000 -0500
@@ -0,0 +1,158 @@
+#source: tlsgdesc.s
+#as: --32
+#ld: -shared -melf_i386
+#objdump: -drj.text
+#target: i?86-*-*
+
+.*: +file format elf32-i386
+
+Disassembly of section .text:
+
+[0-9a-f]+ <fc1>:
+ [0-9a-f]+:	55[ 	]+push   %ebp
+ [0-9a-f]+:	89 e5[ 	]+mov    %esp,%ebp
+ [0-9a-f]+:	53[ 	]+push   %ebx
+ [0-9a-f]+:	50[ 	]+push   %eax
+ [0-9a-f]+:	e8 00 00 00 00[ 	]+call   [0-9a-f]+ <.*>
+ [0-9a-f]+:	5b[ 	]+pop    %ebx
+ [0-9a-f]+:	81 c3 be 11 00 00[ 	]+add    \$0x[0-9a-f]+,%ebx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b e0 ff ff ff[ 	]+sub    0xffffffe0\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	sG3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b f0 ff ff ff[ 	]+add    0xfffffff0\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sG4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD
+ [0-9a-f]+:	8d 04 1d f8 ff ff ff[ 	]+lea    0xfffffff8\(,%ebx,1\),%eax
+#				->R_386_TLS_DTPMOD32	sG1
+ [0-9a-f]+:	e8 a9 ff ff ff[ 	]+call   [0-9a-f]+ <___tls_get_addr@plt>
+#				->R_386_JUMP_SLOT	___tls_get_addr
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 83 18 00 00 00[ 	]+lea    0x18\(%ebx\),%eax
+#				->R_386_TLS_DESC	sG1
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 83 10 00 00 00[ 	]+lea    0x10\(%ebx\),%eax
+#				->R_386_TLS_DESC	sG2
+ [0-9a-f]+:	ff 10[ 	]+call   \*\(%eax\)
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8d 04 1d e8 ff ff ff[ 	]+lea    0xffffffe8\(,%ebx,1\),%eax
+#				->R_386_TLS_DTPMOD32	sG2
+ [0-9a-f]+:	e8 81 ff ff ff[ 	]+call   [0-9a-f]+ <___tls_get_addr@plt>
+#				->R_386_JUMP_SLOT	___tls_get_addr
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gottpoff too
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	2b 83 e0 ff ff ff[ 	]+sub    0xffffffe0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG3
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 83 e0 ff ff ff[ 	]+mov    0xffffffe0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG3
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gotntpoff too
+ [0-9a-f]+:	8b 83 f0 ff ff ff[ 	]+mov    0xfffffff0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	03 83 f0 ff ff ff[ 	]+add    0xfffffff0\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG4
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gotntpoff too
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	03 83 e4 ff ff ff[ 	]+add    0xffffffe4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 83 e4 ff ff ff[ 	]+mov    0xffffffe4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF	sG5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through @gottpoff too
+ [0-9a-f]+:	8b 83 f4 ff ff ff[ 	]+mov    0xfffffff4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG6
+ [0-9a-f]+:	f7 d8[ 	]+neg    %eax
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	65 a1 00 00 00 00[ 	]+mov    %gs:0x0,%eax
+ [0-9a-f]+:	2b 83 f4 ff ff ff[ 	]+sub    0xfffffff4\(%ebx\),%eax
+#				->R_386_TLS_TPOFF32	sG6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gotntpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	03 8b e4 ff ff ff[ 	]+add    0xffffffe4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF	sG5
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+#  @gottpoff IE against global var
+ [0-9a-f]+:	65 8b 0d 00 00 00 00[ 	]+mov    %gs:0x0,%ecx
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	2b 8b f4 ff ff ff[ 	]+sub    0xfffffff4\(%ebx\),%ecx
+#				->R_386_TLS_TPOFF32	sG6
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	90[ 	]+nop *
+ [0-9a-f]+:	8b 5d fc[ 	]+mov    0xfffffffc\(%ebp\),%ebx
+ [0-9a-f]+:	c9[ 	]+leave *
+ [0-9a-f]+:	c3[ 	]+ret *
Index: ld/testsuite/ld-i386/tlsgdesc.rd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-i386/tlsgdesc.rd	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,107 @@
+#source: tlsgdesc.s
+#as: --32
+#ld: -shared -melf_i386
+#readelf: -Ssrl
+#target: i?86-*-*
+
+There are [0-9]+ section headers, starting at offset 0x.*:
+
+Section Headers:
+  \[Nr\] Name +Type +Addr +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+  \[ 1\] \.hash +.*
+  \[ 2\] \.dynsym +.*
+  \[ 3\] \.dynstr +.*
+  \[ 4\] \.rel.dyn +.*
+  \[ 5\] \.rel.plt +.*
+  \[ 6\] \.plt +.*
+  \[ 7\] \.text +.*
+  \[ 8\] \.dynamic +.*
+  \[ 9\] \.got +.*
+  \[10\] \.got.plt +.*
+  \[11\] \.shstrtab +.*
+  \[12\] \.symtab +.*
+  \[13\] \.strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x[0-9a-f]+
+There are [0-9]+ program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  LOAD.*
+  LOAD.*
+  DYNAMIC.*
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +.hash .dynsym .dynstr .rel.dyn .rel.plt .plt .text *
+   01 +.dynamic .got .got.plt *
+   02 +.dynamic *
+
+Relocation section '.rel.dyn' at offset 0x[0-9a-f]+ contains 8 entries:
+ Offset +Info +Type +Sym.Value +Sym. Name
+[0-9a-f]+ +0+225 R_386_TLS_TPOFF32 0+   sG3
+[0-9a-f]+ +0+30e R_386_TLS_TPOFF   0+   sG5
+[0-9a-f]+ +0+423 R_386_TLS_DTPMOD3 0+   sG2
+[0-9a-f]+ +0+424 R_386_TLS_DTPOFF3 0+   sG2
+[0-9a-f]+ +0+50e R_386_TLS_TPOFF   0+   sG4
+[0-9a-f]+ +0+725 R_386_TLS_TPOFF32 0+   sG6
+[0-9a-f]+ +0+923 R_386_TLS_DTPMOD3 0+   sG1
+[0-9a-f]+ +0+924 R_386_TLS_DTPOFF3 0+   sG1
+
+Relocation section '.rel.plt' at offset 0x[0-9a-f]+ contains 3 entries:
+ Offset     Info    Type            Sym.Value  Sym. Name
+[0-9a-f]+  0+c07 R_386_JUMP_SLOT   0+   ___tls_get_addr
+[0-9a-f]+  0+929 R_386_TLS_DESC    0+   sG1
+[0-9a-f]+  0+429 R_386_TLS_DESC    0+   sG2
+
+Symbol table '.dynsym' contains 13 entries:
+ +Num: + Value  Size Type + Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND ___tls_get_addr
+
+Symbol table '.symtab' contains 27 entries:
+ +Num: +Value  Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _DYNAMIC
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND ___tls_get_addr
Index: ld/testsuite/ld-i386/tlsgdesc.s
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-i386/tlsgdesc.s	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,100 @@
+	.text
+	.globl	fc1
+	.type	fc1,@function
+fc1:
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%ebx
+	pushl	%eax
+	call	1f
+1:	popl	%ebx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sG3@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sG4@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sG1@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sG1@tlsdesc(%ebx), %eax
+	call	*sG1@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sG2@tlsdesc(%ebx), %eax
+	call	*sG2@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD */
+	leal	sG2@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE tpoff */
+	leal	sG3@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE tpoff */
+	leal	sG3@tlsdesc(%ebx), %eax
+	call	*sG3@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE ntpoff */
+	leal	sG4@tlsdesc(%ebx), %eax
+	call	*sG4@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE ntpoff */
+	leal	sG4@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE ntpoff */
+	leal	sG5@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE ntpoff */
+	leal	sG5@tlsdesc(%ebx), %eax
+	call	*sG5@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE tpoff */
+	leal	sG6@tlsdesc(%ebx), %eax
+	call	*sG6@tlscall(%eax)
+	nop;nop;nop;nop
+
+	/* GD -> IE tpoff */
+	leal	sG6@tlsgd(,%ebx,1), %eax
+	call	___tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* @gotntpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	addl	sG5@gotntpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	/* @gottpoff IE against global var  */
+	movl	%gs:0, %ecx
+	nop;nop
+	subl	sG6@gottpoff(%ebx), %ecx
+	nop;nop;nop;nop
+
+	movl    -4(%ebp), %ebx
+	leave
+	ret
Index: ld/testsuite/ld-x86-64/tlsbindesc.dd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.dd	2006-01-14 12:34:13.000000000 -0500
@@ -0,0 +1,307 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -drj.text
+#target: x86_64-*-*
+
+# PT_TLS layout is:
+# Offset from   Offset from     Name
+# TCB base      TCB end
+# 0x00          -0xa0           sg1..sg8
+# 0x20          -0x80           sl1..sl8
+# 0x40          -0x60           sh1..sh8
+# 0x60          -0x40           bg1..bg8
+# 0x80          -0x20           bl1..bl8
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .text:
+
+0+401000 <fn2>:
+  [0-9a-f]+:	55[ 	]+push   %rbp
+  [0-9a-f]+:	48 89 e5[ 	]+mov    %rsp,%rbp
+#  GD -> IE because variable is not defined in executable
+  [0-9a-f]+:	48 8b 05 65 03 10 00[ 	]+mov    1049445\(%rip\),%rax +# 501370 <.*>
+#				-> R_X86_64_TPOFF64	sG1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is not defined in executable where
+#  the variable is referenced through IE too
+  [0-9a-f]+:	48 8b 05 48 03 10 00[ 	]+mov    1049416\(%rip\),%rax +# 501360 <.*>
+#				-> R_X86_64_TPOFF64	sG2
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with global variable defined in executable
+  [0-9a-f]+:	48 c7 c0 60 ff ff ff[ 	]+mov    \$0xf+60,%rax
+#							sg1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with local variable defined in executable
+  [0-9a-f]+:	48 c7 c0 80 ff ff ff[ 	]+mov    \$0xf+80,%rax
+#							sl1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  GD -> LE with hidden variable defined in executable
+  [0-9a-f]+:	48 c7 c0 a0 ff ff ff[ 	]+mov    \$0xf+a0,%rax
+#							sh1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LD -> LE
+  [0-9a-f]+:	48 c7 c0 60 ff ff ff[ 	]+mov    \$0xf+60,%rax
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 90 81 ff ff ff[ 	]+lea    0xf+81\(%rax\),%rdx
+#							sl1+1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4c 8d 88 86 ff ff ff[ 	]+lea    0xf+86\(%rax\),%r9
+#							sl2+2
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LD -> LE against hidden variables
+  [0-9a-f]+:	48 8d 90 a0 ff ff ff[ 	]+lea    0xf+a0\(%rax\),%rdx
+#							sh1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 88 a7 ff ff ff[ 	]+lea    0xf+a7\(%rax\),%rcx
+#							sh2+3
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE against global var
+  [0-9a-f]+:	64 4c 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%r9
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4c 03 0d d6 02 10 00[ 	]+add    1049302\(%rip\),%r9 +# 501360 <.*>
+#				-> R_X86_64_TPOFF64	sG2
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against global var defined in exec
+  [0-9a-f]+:	64 4c 8b 14 25 00 00[ 	]+mov    %fs:0x0,%r10
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4d 8d 92 60 ff ff ff[ 	]+lea    0xf+60\(%r10\),%r10
+#							sg1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against local var
+  [0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 80 80 ff ff ff[ 	]+lea    0xf+80\(%rax\),%rax
+#							sl1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against hidden var
+  [0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 89 a0 ff ff ff[ 	]+lea    0xf+a0\(%rcx\),%rcx
+#							sh1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  Direct access through %fs
+#  IE against global var
+  [0-9a-f]+:	48 8b 0d 81 02 10 00[ 	]+mov    1049217\(%rip\),%rcx +# 501358 <.*>
+#				-> R_X86_64_TPOFF64	sG5
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 11[ 	]+mov    %fs:\(%rcx\),%rdx
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE->LE against local var
+  [0-9a-f]+:	49 c7 c3 90 ff ff ff[ 	]+mov    \$0xf+90,%r11
+#							sl5
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 4d 8b 23[ 	]+mov    %fs:\(%r11\),%r12
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE->LE against hidden var
+  [0-9a-f]+:	48 c7 c2 b0 ff ff ff[ 	]+mov    \$0xf+b0,%rdx
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 12[ 	]+mov    %fs:\(%rdx\),%rdx
+#							sh5
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	c9[ 	]+leaveq *
+  [0-9a-f]+:	c3[ 	]+retq *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+
+[0-9a-f]+ <_start>:
+  [0-9a-f]+:	55[ 	]+push   %rbp
+  [0-9a-f]+:	48 89 e5[ 	]+mov    %rsp,%rbp
+#  IE against global var
+  [0-9a-f]+:	64 4c 8b 1c 25 00 00[ 	]+mov    %fs:0x0,%r11
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4c 03 1d 4a 02 10 00[ 	]+add    1049162\(%rip\),%r11 +# 501368 <.*>
+#				-> R_X86_64_TPOFF64	sG6
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against global var defined in exec
+  [0-9a-f]+:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 92 d4 ff ff ff[ 	]+lea    0xf+d4\(%rdx\),%rdx
+#							bg6
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against local var
+  [0-9a-f]+:	64 4c 8b 24 25 00 00[ 	]+mov    %fs:0x0,%r12
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	49 81 c4 f4 ff ff ff[ 	]+add    \$0xf+f4,%r12
+#							bl6
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  direct %fs access IE -> LE against local var
+  [0-9a-f]+:	48 c7 c2 fc ff ff ff[ 	]+mov    \$0xf+fc,%rdx
+#							bl8
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 02[ 	]+mov    %fs:\(%rdx\),%rax
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  IE -> LE against hidden but not local var
+  [0-9a-f]+:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 92 b4 ff ff ff[ 	]+lea    0xf+b4\(%rdx\),%rdx
+#							sh6
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  direct %fs access IE -> LE against hidden but not local var
+  [0-9a-f]+:	48 c7 c2 bc ff ff ff[ 	]+mov    \$0xf+bc,%rdx
+#							sh8
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 02[ 	]+mov    %fs:\(%rdx\),%rax
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, global var defined in exec
+  [0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 8d 90 64 ff ff ff[ 	]+lea    0xf+64\(%rax\),%rdx
+#							sg2
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, local var, non-canonical sequence
+  [0-9a-f]+:	49 c7 c1 e6 ff ff ff[ 	]+mov    \$0xf+e6,%r9
+#							bl2+2
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	4c 01 ca[ 	]+add    %r9,%rdx
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, hidden var defined in exec, non-canonical sequence
+  [0-9a-f]+:	64 48 8b 14 25 00 00[ 	]+mov    %fs:0x0,%rdx
+  [0-9a-f]+:	00 00 *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	48 81 c2 a5 ff ff ff[ 	]+add    \$0xf+a5,%rdx
+#							sh2+1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  Direct %fs access
+#  LE, global var defined in exec
+  [0-9a-f]+:	64 48 8b 04 25 68 ff[ 	]+mov    %fs:0xf+68,%rax
+  [0-9a-f]+:	ff ff *
+#							sg3
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, local var
+  [0-9a-f]+:	64 4c 8b 14 25 eb ff[ 	]+mov    %fs:0xf+eb,%r10
+  [0-9a-f]+:	ff ff *
+#							bl3+3
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+#  LE, hidden var defined in exec
+  [0-9a-f]+:	64 48 8b 14 25 a9 ff[ 	]+mov    %fs:0xf+a9,%rdx
+  [0-9a-f]+:	ff ff *
+#							sh3+1
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	90[ 	]+nop *
+  [0-9a-f]+:	c9[ 	]+leaveq *
+  [0-9a-f]+:	c3[ 	]+retq *
Index: ld/testsuite/ld-x86-64/tlsbindesc.rd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.rd	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,141 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --64
+#ld: -shared -melf_x86_64
+#readelf: -WSsrl
+#target: x86_64-*-*
+
+There are 15 section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+  \[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 00 +0 +0 +0
+  \[ 1\] .interp +.*
+  \[ 2\] .hash +.*
+  \[ 3\] .dynsym +.*
+  \[ 4\] .dynstr +.*
+  \[ 5\] .rela.dyn +.*
+  \[ 6\] .text +PROGBITS +0+401000 0+1000 0+1f6 00 +AX +0 +0 +4096
+  \[ 7\] .tdata +PROGBITS +0+5011f6 0+11f6 0+60 00 WAT +0 +0 +1
+  \[ 8\] .tbss +NOBITS +0+501256 0+1256 0+40 00 WAT +0 +0 +1
+  \[ 9\] .dynamic +DYNAMIC +0+501258 0+1258 0+100 10 +WA +4 +0 +8
+  \[10\] .got +PROGBITS +0+501358 0+1358 0+20 08 +WA +0 +0 +8
+  \[11\] .got.plt +PROGBITS +0+501378 0+1378 0+18 08 +WA +0 +0 +8
+  \[12\] .shstrtab +.*
+  \[13\] .symtab +.*
+  \[14\] .strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is EXEC \(Executable file\)
+Entry point 0x401108
+There are 6 program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  PHDR.*
+  INTERP.*
+.*Requesting program interpreter.*
+  LOAD +0x0+ 0x0+400000 0x0+400000 0x0+11f6 0x0+11f6 R E 0x100000
+  LOAD +0x0+11f6 0x0+5011f6 0x0+5011f6 0x0+19a 0x0+19a RW  0x100000
+  DYNAMIC +0x0+1258 0x0+501258 0x0+501258 0x0+100 0x0+100 RW  0x8
+  TLS +0x0+11f6 0x0+5011f6 0x0+5011f6 0x0+60 0x0+a0 R +0x1
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 *
+   01 +.interp *
+   02 +.interp .hash .dynsym .dynstr .rela.dyn .text *
+   03 +.tdata .dynamic .got .got.plt *
+   04 +.dynamic *
+   05 +.tdata .tbss *
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 4 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+0+501358  0+100000012 R_X86_64_TPOFF64 +0+ sG5 \+ 0
+0+501360  0+200000012 R_X86_64_TPOFF64 +0+ sG2 \+ 0
+0+501368  0+400000012 R_X86_64_TPOFF64 +0+ sG6 \+ 0
+0+501370  0+500000012 R_X86_64_TPOFF64 +0+ sG1 \+ 0
+
+Symbol table '.dynsym' contains 8 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+[0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: 0+[0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: 0+[0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 67 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +[0-9]+: 0+20 +0 TLS +LOCAL  DEFAULT +7 sl1
+ +[0-9]+: 0+24 +0 TLS +LOCAL  DEFAULT +7 sl2
+ +[0-9]+: 0+28 +0 TLS +LOCAL  DEFAULT +7 sl3
+ +[0-9]+: 0+2c +0 TLS +LOCAL  DEFAULT +7 sl4
+ +[0-9]+: 0+30 +0 TLS +LOCAL  DEFAULT +7 sl5
+ +[0-9]+: 0+34 +0 TLS +LOCAL  DEFAULT +7 sl6
+ +[0-9]+: 0+38 +0 TLS +LOCAL  DEFAULT +7 sl7
+ +[0-9]+: 0+3c +0 TLS +LOCAL  DEFAULT +7 sl8
+ +[0-9]+: 0+80 +0 TLS +LOCAL  DEFAULT +8 bl1
+ +[0-9]+: 0+84 +0 TLS +LOCAL  DEFAULT +8 bl2
+ +[0-9]+: 0+88 +0 TLS +LOCAL  DEFAULT +8 bl3
+ +[0-9]+: 0+8c +0 TLS +LOCAL  DEFAULT +8 bl4
+ +[0-9]+: 0+90 +0 TLS +LOCAL  DEFAULT +8 bl5
+ +[0-9]+: 0+94 +0 TLS +LOCAL  DEFAULT +8 bl6
+ +[0-9]+: 0+98 +0 TLS +LOCAL  DEFAULT +8 bl7
+ +[0-9]+: 0+9c +0 TLS +LOCAL  DEFAULT +8 bl8
+ +[0-9]+: 0+0 +0 TLS +LOCAL  HIDDEN +7 _TLS_MODULE_BASE_
+ +[0-9]+: 0+501258 +0 OBJECT  LOCAL  HIDDEN    9 _DYNAMIC
+ +[0-9]+: 0+501378 +0 OBJECT  LOCAL  HIDDEN   11 _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +7 sg8
+ +[0-9]+: 0+7c +0 TLS +GLOBAL DEFAULT +8 bg8
+ +[0-9]+: 0+74 +0 TLS +GLOBAL DEFAULT +8 bg6
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+68 +0 TLS +GLOBAL DEFAULT +8 bg3
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +7 sg3
+ +[0-9]+: 0+48 +0 TLS +GLOBAL HIDDEN +7 sh3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +7 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +7 sg5
+ +[0-9]+: 0+70 +0 TLS +GLOBAL DEFAULT +8 bg5
+ +[0-9]+: 0+58 +0 TLS +GLOBAL HIDDEN +7 sh7
+ +[0-9]+: 0+5c +0 TLS +GLOBAL HIDDEN +7 sh8
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +7 sg1
+ +[0-9]+: 0+401108 +0 FUNC +GLOBAL DEFAULT +6 _start
+ +[0-9]+: 0+4c +0 TLS +GLOBAL HIDDEN +7 sh4
+ +[0-9]+: 0+78 +0 TLS +GLOBAL DEFAULT +8 bg7
+ +[0-9]+: 0+50 +0 TLS +GLOBAL HIDDEN +7 sh5
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: 0+401000 +0 FUNC +GLOBAL DEFAULT +6 fn2
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +7 sg2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: 0+40 +0 TLS +GLOBAL HIDDEN +7 sh1
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +7 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +7 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+ +[0-9]+: 0+44 +0 TLS +GLOBAL HIDDEN +7 sh2
+ +[0-9]+: 0+54 +0 TLS +GLOBAL HIDDEN +7 sh6
+ +[0-9]+: 0+64 +0 TLS +GLOBAL DEFAULT +8 bg2
+ +[0-9]+: 0+60 +0 TLS +GLOBAL DEFAULT +8 bg1
+ +[0-9]+: 0+6c +0 TLS +GLOBAL DEFAULT +8 bg4
Index: ld/testsuite/ld-x86-64/tlsbindesc.s
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.s	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,128 @@
+	/* Force .data aligned to 4K, so that .got very likely gets at
+	   0x5021a0 (0x60 bytes .tdata and 0x140 bytes .dynamic)  */
+	.data
+	.balign	4096
+	.section ".tdata", "awT", @progbits
+	.globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8
+	.globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+	.hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	/* Force .text aligned to 4K, so it very likely gets at 0x401000.  */
+	.text
+	.balign	4096
+	.globl	fn2
+	.type	fn2,@function
+fn2:
+	pushq	%rbp
+	movq	%rsp, %rbp
+
+	/* GD -> IE because variable is not defined in executable */
+	leaq	sG1@tlsdesc(%rip), %rax
+	call	*sG1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is not defined in executable where
+	   the variable is referenced through IE too */
+	leaq	sG2@tlsdesc(%rip), %rax
+	call	*sG2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with global variable defined in executable */
+	leaq	sg1@tlsdesc(%rip), %rax
+	call	*sg1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with local variable defined in executable */
+	leaq	sl1@tlsdesc(%rip), %rax
+	call	*sl1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> LE with hidden variable defined in executable */
+	leaq	sh1@tlsdesc(%rip), %rax
+	call	*sh1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* LD -> LE */
+	leaq	_TLS_MODULE_BASE_@tlsdesc(%rip), %rax
+	call	*_TLS_MODULE_BASE_@tlscall(%rax)
+	nop;nop
+	leaq	1+sl1@dtpoff(%rax), %rdx
+	nop;nop
+	leaq	sl2@dtpoff+2(%rax), %r9
+	nop;nop;nop;nop
+
+	/* LD -> LE against hidden variables */
+	leaq	sh1@dtpoff(%rax), %rdx
+	nop;nop
+	leaq	3+sh2@dtpoff(%rax), %rcx
+	nop;nop;nop;nop
+
+	/* IE against global var  */
+	movq	%fs:0, %r9
+	nop;nop
+	addq	sG2@gottpoff(%rip), %r9
+	nop;nop;nop;nop
+
+	/* IE -> LE against global var defined in exec */
+	movq	%fs:0, %r10
+	nop;nop
+	addq	sg1@gottpoff(%rip), %r10
+	nop;nop;nop;nop
+
+	/* IE -> LE against local var */
+	movq	%fs:0, %rax
+	nop;nop
+	addq	sl1@gottpoff(%rip), %rax
+	nop;nop;nop;nop
+
+	/* IE -> LE against hidden var */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sh1@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* Direct access through %fs  */
+
+	/* IE against global var  */
+	movq	sG5@gottpoff(%rip), %rcx
+	nop;nop
+	movq	%fs:(%rcx), %rdx
+	nop;nop;nop;nop
+
+	/* IE->LE against local var  */
+	movq	sl5@gottpoff(%rip), %r11
+	nop;nop
+	movq	%fs:(%r11), %r12
+	nop;nop;nop;nop
+
+	/* IE->LE against hidden var  */
+	movq	sh5@gottpoff(%rip), %rdx
+	nop;nop
+	movq	%fs:(%rdx), %rdx
+	nop;nop;nop;nop
+
+	leave
+	ret
Index: ld/testsuite/ld-x86-64/tlsbindesc.sd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.sd	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,12 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -sj.got
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Contents of section .got:
+ 501358 00000000 00000000 00000000 00000000  .*
+ 501368 00000000 00000000 00000000 00000000  .*
Index: ld/testsuite/ld-x86-64/tlsbindesc.td
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-x86-64/tlsbindesc.td	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,16 @@
+#source: tlsbindesc.s
+#source: tlsbin.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -sj.tdata
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Contents of section .tdata:
+ 5011f6 11000000 12000000 13000000 14000000  .*
+ 501206 15000000 16000000 17000000 18000000  .*
+ 501216 41000000 42000000 43000000 44000000  .*
+ 501226 45000000 46000000 47000000 48000000  .*
+ 501236 01010000 02010000 03010000 04010000  .*
+ 501246 05010000 06010000 07010000 08010000  .*
Index: ld/testsuite/ld-x86-64/tlsdesc.dd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-x86-64/tlsdesc.dd	2006-01-14 12:32:42.000000000 -0500
@@ -0,0 +1,204 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -drj.text
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .text:
+
+0+[0-9a-f]+ <fn1>:
+ +[0-9a-f]+:	55[ 	]+push   %rbp
+ +[0-9a-f]+:	48 89 e5[ 	]+mov    %rsp,%rbp
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD
+ +[0-9a-f]+:	48 8d 05 89 03 10 00[ 	]+lea    1049481\(%rip\),%rax +# 101398 <.*>
+#				-> R_X86_64_TLSDESC	sg1
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE because variable is referenced through IE too
+ +[0-9a-f]+:	48 8b 05 1c 03 10 00[ 	]+mov    1049372\(%rip\),%rax +# 101338 <.*>
+#				-> R_X86_64_TPOFF64	sg2
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD against local variable
+ +[0-9a-f]+:	48 8d 05 3f 03 10 00[ 	]+lea    1049407\(%rip\),%rax +# 101368 <.*>
+#				-> R_X86_64_TLSDESC	[0 0x2000000000000000]
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against local variable referenced through IE too
+ +[0-9a-f]+:	48 8b 05 d2 02 10 00[ 	]+mov    1049298\(%rip\),%rax +# 101308 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x24
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD against hidden and local variable
+ +[0-9a-f]+:	48 8d 05 65 03 10 00[ 	]+lea    1049445\(%rip\),%rax +# 1013a8 <.*>
+#				-> R_X86_64_TLSDESC	[0 0x4000000000000000]
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden and local variable referenced through IE too
+ +[0-9a-f]+:	48 8b 05 f0 02 10 00[ 	]+mov    1049328\(%rip\),%rax +# 101340 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x44
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD against hidden but not local variable
+ +[0-9a-f]+:	48 8d 05 1b 03 10 00[ 	]+lea    1049371\(%rip\),%rax +# 101378 <.*>
+#				-> R_X86_64_TLSDESC	[0 0x6000000000000000]
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  GD -> IE against hidden but not local variable referenced through IE too
+ +[0-9a-f]+:	48 8b 05 ae 02 10 00[ 	]+mov    1049262\(%rip\),%rax +# 101318 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x64
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  LD
+ +[0-9a-f]+:	48 8d 05 11 03 10 00[ 	]+lea    1049361\(%rip\),%rax +# 101388 <.*>
+#				-> R_X86_64_TLSDESC	[0 0x000000000000000]
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8d 90 20 00 00 00[ 	]+lea    0x20\(%rax\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	4c 8d 88 26 00 00 00[ 	]+lea    0x26\(%rax\),%r9
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  LD against hidden and local variables
+ +[0-9a-f]+:	48 8d 90 40 00 00 00[ 	]+lea    0x40\(%rax\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8d 88 47 00 00 00[ 	]+lea    0x47\(%rax\),%rcx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  LD against hidden but not local variables
+ +[0-9a-f]+:	4c 8d a0 60 00 00 00[ 	]+lea    0x60\(%rax\),%r12
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8d 88 65 00 00 00[ 	]+lea    0x65\(%rax\),%rcx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against global var
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 71 02 10 00[ 	]+add    1049201\(%rip\),%rcx +# 101338 <.*>
+#				-> R_X86_64_TPOFF64	sg2
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against local var
+ +[0-9a-f]+:	64 4c 8b 34 25 00 00[ 	]+mov    %fs:0x0,%r14
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	4c 03 35 2b 02 10 00[ 	]+add    1049131\(%rip\),%r14 +# 101308 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x24
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against hidden and local var
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 4d 02 10 00[ 	]+add    1049165\(%rip\),%rcx +# 101340 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x44
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against hidden but not local var
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 0f 02 10 00[ 	]+add    1049103\(%rip\),%rcx +# 101318 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x64
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  Direct access through %fs
+#  IE against global var
+ +[0-9a-f]+:	48 8b 0d 0c 02 10 00[ 	]+mov    1049100\(%rip\),%rcx +# 101320 <.*>
+#				-> R_X86_64_TPOFF64	sg5
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 11[ 	]+mov    %fs:\(%rcx\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against local var
+ +[0-9a-f]+:	4c 8b 15 eb 01 10 00[ 	]+mov    1049067\(%rip\),%r10 +# 101310 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x30
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 4d 8b 22[ 	]+mov    %fs:\(%r10\),%r12
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against hidden and local var
+ +[0-9a-f]+:	48 8b 15 f2 01 10 00[ 	]+mov    1049074\(%rip\),%rdx +# 101328 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x50
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 12[ 	]+mov    %fs:\(%rdx\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+#  IE against hidden but not local var
+ +[0-9a-f]+:	48 8b 0d e9 01 10 00[ 	]+mov    1049065\(%rip\),%rcx +# 101330 <.*>
+#				-> R_X86_64_TPOFF64	*ABS*+0x70
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 11[ 	]+mov    %fs:\(%rcx\),%rdx
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	c9[ 	]+leaveq *
+ +[0-9a-f]+:	c3[ 	]+retq *
+ +[0-9a-f]+:	90[ 	]+nop *
Index: ld/testsuite/ld-x86-64/tlsdesc.pd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-x86-64/tlsdesc.pd	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,26 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -drj.plt
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .plt:
+
+0000000000000470 <.*@plt-0x10>:
+ 470:	ff 35 e2 0e 10 00    	pushq  1052386\(%rip\)        # 101358 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ 476:	ff 25 e4 0e 10 00    	jmpq   \*1052388\(%rip\)        # 101360 <_GLOBAL_OFFSET_TABLE_\+0x10>
+ 47c:	90                   	nop *
+ 47d:	90                   	nop *
+ 47e:	90                   	nop *
+ 47f:	90                   	nop *
+0000000000000480 <.*@plt>:
+ 480:	ff 35 d2 0e 10 00    	pushq  1052370\(%rip\)        # 101358 <_GLOBAL_OFFSET_TABLE_\+0x8>
+ 486:	ff 25 bc 0e 10 00    	jmpq   \*1052348\(%rip\)        # 101348 <_DYNAMIC\+0x190>
+ 48c:	90                   	nop *
+ 48d:	90                   	nop *
+ 48e:	90                   	nop *
+ 48f:	90                   	nop *
+
Index: ld/testsuite/ld-x86-64/tlsdesc.rd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-x86-64/tlsdesc.rd	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,164 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#readelf: -WSsrld
+#target: x86_64-*-*
+
+There are 16 section headers, starting at offset 0x[0-9a-f]+:
+
+Section Headers:
+  \[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 00 +0 +0 +0
+  \[ 1\] .hash +.*
+  \[ 2\] .dynsym +.*
+  \[ 3\] .dynstr +.*
+  \[ 4\] .rela.dyn +.*
+  \[ 5\] .rela.plt +.*
+  \[ 6\] .plt +PROGBITS +0+470 0+470 0+20 10 +AX +0 +0 +4
+  \[ 7\] .text +PROGBITS +0+1000 0+1000 0+154 00 +AX +0 +0 4096
+  \[ 8\] .tdata +PROGBITS +0+101154 0+1154 0+60 00 WAT +0 +0 +1
+  \[ 9\] .tbss +NOBITS +0+1011b4 0+11b4 0+20 00 WAT +0 +0 +1
+  \[10\] .dynamic +DYNAMIC +0+1011b8 0+11b8 0+150 10 +WA +3 +0 +8
+  \[11\] .got +PROGBITS +0+101308 0+1308 0+48 08 +WA +0 +0 +8
+  \[12\] .got.plt +PROGBITS +0+101350 0+1350 0+68 08 +WA +0 +0 +8
+  \[13\] .shstrtab +.*
+  \[14\] .symtab +.*
+  \[15\] .strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x1000
+There are 4 program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  LOAD +0x0+ 0x0+ 0x0+ 0x[0-9a-f]+ 0x[0-9a-f]+ R E 0x100000
+  LOAD +0x0+1154 0x0+101154 0x0+101154 0x0+264 0x0+264 RW +0x100000
+  DYNAMIC +0x0+11b8 0x0+1011b8 0x0+1011b8 0x0+150 0x0+150 RW +0x8
+  TLS +0x0+1154 0x0+101154 0x0+101154 0x0+60 0x0+80 R +0x1
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +.hash .dynsym .dynstr .rela.dyn .rela.plt .plt .text *
+   01 +.tdata .dynamic .got .got.plt *
+   02 +.dynamic *
+   03 +.tdata .tbss *
+
+Dynamic section at offset 0x[0-9a-f]+ contains 16 entries:
+ +Tag +Type +Name/Value
+ 0x[0-9a-f]+ +\(HASH\).*
+ 0x[0-9a-f]+ +\(STRTAB\).*
+ 0x[0-9a-f]+ +\(SYMTAB\).*
+ 0x[0-9a-f]+ +\(STRSZ\).*
+ 0x[0-9a-f]+ +\(SYMENT\).*
+ 0x[0-9a-f]+ +\(PLTGOT\).*
+ 0x[0-9a-f]+ +\(PLTRELSZ\).*
+ 0x[0-9a-f]+ +\(PLTREL\).*
+ 0x[0-9a-f]+ +\(JMPREL\).*
+ 0x[0-9a-f]+ +\(TLSDESC_PLT\) +0x480
+ 0x[0-9a-f]+ +\(TLSDESC_GOT\) +0x101348
+ 0x[0-9a-f]+ +\(RELA\).*
+ 0x[0-9a-f]+ +\(RELASZ\).*
+ 0x[0-9a-f]+ +\(RELAENT\).*
+ 0x[0-9a-f]+ +\(FLAGS\).*
+ 0x[0-9a-f]+ +\(NULL\).*
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 8 entries:
+ +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
+0+101308  0+12 R_X86_64_TPOFF64 +0+24
+0+101310  0+12 R_X86_64_TPOFF64 +0+30
+0+101318  0+12 R_X86_64_TPOFF64 +0+64
+0+101328  0+12 R_X86_64_TPOFF64 +0+50
+0+101330  0+12 R_X86_64_TPOFF64 +0+70
+0+101340  0+12 R_X86_64_TPOFF64 +0+44
+0+101320  0+700000012 R_X86_64_TPOFF64 +0+10 sg5 \+ 0
+0+101338  0+b00000012 R_X86_64_TPOFF64 +0+4 sg2 \+ 0
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 5 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+0+101398  0+800000024 R_X86_64_TLSDESC +0+ sg1 \+ 0
+0+101368  0+24 R_X86_64_TLSDESC +0+20
+0+1013a8  0+24 R_X86_64_TLSDESC +0+40
+0+101378  0+24 R_X86_64_TLSDESC +0+60
+0+101388  0+24 R_X86_64_TLSDESC +0+
+
+Symbol table '.dynsym' contains 16 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +8 sg8
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +8 sg3
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +8 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +8 sg5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +8 sg1
+ +[0-9]+: 0+1000 +0 FUNC +GLOBAL DEFAULT +7 fn1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +8 sg2
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +8 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +8 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 55 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +14 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +15 *
+ +[0-9]+: 0+20 +0 TLS +LOCAL  DEFAULT +8 sl1
+ +[0-9]+: 0+24 +0 TLS +LOCAL  DEFAULT +8 sl2
+ +[0-9]+: 0+28 +0 TLS +LOCAL  DEFAULT +8 sl3
+ +[0-9]+: 0+2c +0 TLS +LOCAL  DEFAULT +8 sl4
+ +[0-9]+: 0+30 +0 TLS +LOCAL  DEFAULT +8 sl5
+ +[0-9]+: 0+34 +0 TLS +LOCAL  DEFAULT +8 sl6
+ +[0-9]+: 0+38 +0 TLS +LOCAL  DEFAULT +8 sl7
+ +[0-9]+: 0+3c +0 TLS +LOCAL  DEFAULT +8 sl8
+ +[0-9]+: 0+60 +0 TLS +LOCAL  HIDDEN +9 sH1
+ +[0-9]+: 0+ +0 TLS +LOCAL  HIDDEN +8 _TLS_MODULE_BASE_
+ +[0-9]+: 0+1011b8 +0 OBJECT  LOCAL  HIDDEN  ABS _DYNAMIC
+ +[0-9]+: 0+48 +0 TLS +LOCAL  HIDDEN +8 sh3
+ +[0-9]+: 0+64 +0 TLS +LOCAL  HIDDEN +9 sH2
+ +[0-9]+: 0+78 +0 TLS +LOCAL  HIDDEN +9 sH7
+ +[0-9]+: 0+58 +0 TLS +LOCAL  HIDDEN +8 sh7
+ +[0-9]+: 0+5c +0 TLS +LOCAL  HIDDEN +8 sh8
+ +[0-9]+: 0+6c +0 TLS +LOCAL  HIDDEN +9 sH4
+ +[0-9]+: 0+4c +0 TLS +LOCAL  HIDDEN +8 sh4
+ +[0-9]+: 0+68 +0 TLS +LOCAL  HIDDEN +9 sH3
+ +[0-9]+: 0+50 +0 TLS +LOCAL  HIDDEN +8 sh5
+ +[0-9]+: 0+70 +0 TLS +LOCAL  HIDDEN +9 sH5
+ +[0-9]+: 0+74 +0 TLS +LOCAL  HIDDEN +9 sH6
+ +[0-9]+: 0+7c +0 TLS +LOCAL  HIDDEN +9 sH8
+ +[0-9]+: 0+40 +0 TLS +LOCAL  HIDDEN +8 sh1
+ +[0-9]+: 0+101350 +0 OBJECT  LOCAL  HIDDEN  ABS _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+44 +0 TLS +LOCAL  HIDDEN +8 sh2
+ +[0-9]+: 0+54 +0 TLS +LOCAL  HIDDEN +8 sh6
+ +[0-9]+: 0+1c +0 TLS +GLOBAL DEFAULT +8 sg8
+ +[0-9]+: 0+8 +0 TLS +GLOBAL DEFAULT +8 sg3
+ +[0-9]+: 0+c +0 TLS +GLOBAL DEFAULT +8 sg4
+ +[0-9]+: 0+10 +0 TLS +GLOBAL DEFAULT +8 sg5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT +8 sg1
+ +[0-9]+: 0+1000 +0 FUNC +GLOBAL DEFAULT +7 fn1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+4 +0 TLS +GLOBAL DEFAULT +8 sg2
+ +[0-9]+: 0+14 +0 TLS +GLOBAL DEFAULT +8 sg6
+ +[0-9]+: 0+18 +0 TLS +GLOBAL DEFAULT +8 sg7
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
Index: ld/testsuite/ld-x86-64/tlsdesc.s
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-x86-64/tlsdesc.s	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,157 @@
+	/* Force .data aligned to 4K, so .got very likely gets at 0x102190
+	   (0x60 bytes .tdata and 0x130 bytes .dynamic)  */
+        .data
+        .balign 4096
+	.section ".tdata", "awT", @progbits
+	.globl sg1, sg2, sg3, sg4, sg5, sg6, sg7, sg8
+	.globl sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+	.hidden sh1, sh2, sh3, sh4, sh5, sh6, sh7, sh8
+sg1:	.long 17
+sg2:	.long 18
+sg3:	.long 19
+sg4:	.long 20
+sg5:	.long 21
+sg6:	.long 22
+sg7:	.long 23
+sg8:	.long 24
+sl1:	.long 65
+sl2:	.long 66
+sl3:	.long 67
+sl4:	.long 68
+sl5:	.long 69
+sl6:	.long 70
+sl7:	.long 71
+sl8:	.long 72
+sh1:	.long 257
+sh2:	.long 258
+sh3:	.long 259
+sh4:	.long 260
+sh5:	.long 261
+sh6:	.long 262
+sh7:	.long 263
+sh8:	.long 264
+	/* Force .text aligned to 4K, so it very likely gets at 0x1000.  */
+	.text
+	.balign	4096
+	.globl	fn1
+	.type	fn1,@function
+fn1:
+	pushq	%rbp
+	movq	%rsp, %rbp
+	nop;nop;nop;nop
+
+	/* GD */
+	leaq	sg1@tlsdesc(%rip), %rax
+	call	*sg1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE because variable is referenced through IE too */
+	leaq	sg2@tlsdesc(%rip), %rax
+	call	*sg2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD against local variable */
+	leaq	sl1@tlsdesc(%rip), %rax
+	call	*sl1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against local variable referenced through IE too */
+	leaq	sl2@tlsdesc(%rip), %rax
+	call	*sl2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD against hidden and local variable */
+	leaq	sh1@tlsdesc(%rip), %rax
+	call	*sh1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden and local variable referenced through
+	   IE too */
+	leaq	sh2@tlsdesc(%rip), %rax
+	call	*sh2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD against hidden but not local variable */
+	leaq	sH1@tlsdesc(%rip), %rax
+	call	*sH1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE against hidden but not local variable referenced through
+	   IE too */
+	leaq	sH2@tlsdesc(%rip), %rax
+	call	*sH2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* LD */
+	leaq	_TLS_MODULE_BASE_@tlsdesc(%rip), %rax
+	call	*_TLS_MODULE_BASE_@tlscall(%rax)
+	nop;nop
+	leaq	sl1@dtpoff(%rax), %rdx
+	nop;nop
+	leaq	2+sl2@dtpoff(%rax), %r9
+	nop;nop;nop;nop
+
+	/* LD against hidden and local variables */
+	leaq	sh1@dtpoff(%rax), %rdx
+	nop;nop
+	leaq	sh2@dtpoff+3(%rax), %rcx
+	nop;nop;nop;nop
+
+	/* LD against hidden but not local variables */
+	leaq	sH1@dtpoff(%rax), %r12
+	nop;nop
+	leaq	sH2@dtpoff+1(%rax), %rcx
+	nop;nop
+
+	/* IE against global var  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sg2@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* IE against local var  */
+	movq	%fs:0, %r14
+	nop;nop
+	addq	sl2@gottpoff(%rip), %r14
+	nop;nop;nop;nop
+
+	/* IE against hidden and local var  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sh2@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* IE against hidden but not local var  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sH2@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* Direct access through %fs  */
+
+	/* IE against global var  */
+	movq	sg5@gottpoff(%rip), %rcx
+	nop;nop
+	movq	%fs:(%rcx), %rdx
+	nop;nop;nop;nop
+
+	/* IE against local var  */
+	movq	sl5@gottpoff(%rip), %r10
+	nop;nop
+	movq	%fs:(%r10), %r12
+	nop;nop;nop;nop
+
+	/* IE against hidden and local var  */
+	movq	sh5@gottpoff(%rip), %rdx
+	nop;nop
+	movq	%fs:(%rdx), %rdx
+	nop;nop;nop;nop
+
+	/* IE against hidden but not local var  */
+	movq	sH5@gottpoff(%rip), %rcx
+	nop;nop
+	movq	%fs:(%rcx), %rdx
+	nop;nop;nop;nop
+
+	leave
+	ret
Index: ld/testsuite/ld-x86-64/tlsdesc.sd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-x86-64/tlsdesc.sd	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,23 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -s -j.got -j.got.plt
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Contents of section \.got:
+ 101308 00000000 00000000 00000000 00000000  .*
+ 101318 00000000 00000000 00000000 00000000  .*
+ 101328 00000000 00000000 00000000 00000000  .*
+ 101338 00000000 00000000 00000000 00000000  .*
+ 101348 00000000 00000000                    .*
+Contents of section \.got\.plt:
+ 101350 b8111000 00000000 00000000 00000000  .*
+ 101360 00000000 00000000 00000000 00000000  .*
+ 101370 00000000 00000000 00000000 00000000  .*
+ 101380 00000000 00000000 00000000 00000000  .*
+ 101390 00000000 00000000 00000000 00000000  .*
+ 1013a0 00000000 00000000 00000000 00000000  .*
+ 1013b0 00000000 00000000                    .*
Index: ld/testsuite/ld-x86-64/tlsdesc.td
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-x86-64/tlsdesc.td	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,16 @@
+#source: tlsdesc.s
+#source: tlspic2.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -sj.tdata
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Contents of section .tdata:
+ 101154 11000000 12000000 13000000 14000000  .*
+ 101164 15000000 16000000 17000000 18000000  .*
+ 101174 41000000 42000000 43000000 44000000  .*
+ 101184 45000000 46000000 47000000 48000000  .*
+ 101194 01010000 02010000 03010000 04010000  .*
+ 1011a4 05010000 06010000 07010000 08010000  .*
Index: ld/testsuite/ld-x86-64/tlsgdesc.dd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-x86-64/tlsgdesc.dd	2006-01-14 12:43:50.000000000 -0500
@@ -0,0 +1,167 @@
+#source: tlsgdesc.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -drj.text
+#target: x86_64-*-*
+
+.*: +file format elf64-x86-64
+
+Disassembly of section .text:
+
+0+[0-9a-f]+ <fc1>:
+ +[0-9a-f]+:	55[ 	]+push   %rbp
+ +[0-9a-f]+:	48 89 e5[ 	]+mov    %rsp,%rbp
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# IE
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 5e 02 10 00[ 	]+add    1049182\(%rip\),%rcx +# 100660 <.*>
+#				-> R_X86_64_TPOFF64	sG3
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# IE
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 68 02 10 00[ 	]+add    1049192\(%rip\),%rcx +# 100680 <.*>
+#				-> R_X86_64_TPOFF64	sG4
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD, gd first
+ +[0-9a-f]+:	66 48 8d 3d 6c 02 10[ 	]+lea    1049196\(%rip\),%rdi +# 100690 <.*>
+ +[0-9a-f]+:	00 *
+#				-> R_X86_64_DTPMOD64	sG1
+ +[0-9a-f]+:	66 66 48 e8 9c ff ff[ 	]+callq  [0-9a-f]+ <.*>
+ +[0-9a-f]+:	ff[ 	]+
+#				-> R_X86_64_JUMP_SLOT	__tls_get_addr
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8d 05 a1 02 10 00[ 	]+lea    1049249\(%rip\),%rax +# 1006d8 <.*>
+#				-> R_X86_64_TLSDESC	sG1
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD, desc first
+ +[0-9a-f]+:	48 8d 05 84 02 10 00[ 	]+lea    1049220\(%rip\),%rax +# 1006c8 <.*>
+#				-> R_X86_64_TLSDESC	sG2
+ +[0-9a-f]+:	ff 10[ 	]+callq  \*\(%rax\)
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	66 48 8d 3d 1e 02 10[ 	]+lea    1049118\(%rip\),%rdi +# 100670 <.*>
+ +[0-9a-f]+:	00 *
+#				-> R_X86_64_DTPMOD64	sG2
+ +[0-9a-f]+:	66 66 48 e8 6e ff ff[ 	]+callq  [0-9a-f]+ <.*>
+ +[0-9a-f]+:	ff[ 	]+
+#				-> R_X86_64_JUMP_SLOT	__tls_get_addr
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD -> IE, gd first, after IE use
+ +[0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	48 03 05 f2 01 10 00[ 	]+add    1049074\(%rip\),%rax +# 100660 <.*>
+#				-> R_X86_64_TPOFF64	sG3
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8b 05 e7 01 10 00[ 	]+mov    1049063\(%rip\),%rax +# 100660 <.*>
+#				-> R_X86_64_TPOFF64	sG3
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD -> IE, desc first, after IE use
+ +[0-9a-f]+:	48 8b 05 fa 01 10 00[ 	]+mov    1049082\(%rip\),%rax +# 100680 <.*>
+#				-> R_X86_64_TPOFF64	sG4
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	48 03 05 e4 01 10 00[ 	]+add    1049060\(%rip\),%rax +# 100680 <.*>
+#				-> R_X86_64_TPOFF64	sG4
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD -> IE, gd first, before IE use
+ +[0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	48 03 05 b8 01 10 00[ 	]+add    1049016\(%rip\),%rax +# 100668 <.*>
+#				-> R_X86_64_TPOFF64	sG5
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 8b 05 ad 01 10 00[ 	]+mov    1049005\(%rip\),%rax +# 100668 <.*>
+#				-> R_X86_64_TPOFF64	sG5
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# GD -> IE, desc first, before IE use
+ +[0-9a-f]+:	48 8b 05 c0 01 10 00[ 	]+mov    1049024\(%rip\),%rax +# 100688 <.*>
+#				-> R_X86_64_TPOFF64	sG6
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	64 48 8b 04 25 00 00[ 	]+mov    %fs:0x0,%rax
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	48 03 05 aa 01 10 00[ 	]+add    1049002\(%rip\),%rax +# 100688 <.*>
+#				-> R_X86_64_TPOFF64	sG6
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# IE
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 74 01 10 00[ 	]+add    1048948\(%rip\),%rcx +# 100668 <.*>
+#				-> R_X86_64_TPOFF64	sG5
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+# IE
+ +[0-9a-f]+:	64 48 8b 0c 25 00 00[ 	]+mov    %fs:0x0,%rcx
+ +[0-9a-f]+:	00 00 *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	48 03 0d 7e 01 10 00[ 	]+add    1048958\(%rip\),%rcx +# 100688 <.*>
+#				-> R_X86_64_TPOFF64	sG6
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	90[ 	]+nop *
+ +[0-9a-f]+:	c9[ 	]+leaveq *
+ +[0-9a-f]+:	c3[ 	]+retq *
Index: ld/testsuite/ld-x86-64/tlsgdesc.rd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-x86-64/tlsgdesc.rd	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,107 @@
+#source: tlsgdesc.s
+#as: --64
+#ld: -shared -melf64_x86_64
+#readelf: -WSsrl
+#target: x86_64-*-*
+
+There are [0-9]+ section headers, starting at offset 0x.*:
+
+Section Headers:
+  \[Nr\] Name +Type +Address +Off +Size +ES Flg Lk Inf Al
+  \[ 0\] +NULL +0+ 0+ 0+ 0+ +0 +0 +0
+  \[ 1\] \.hash +.*
+  \[ 2\] \.dynsym +.*
+  \[ 3\] \.dynstr +.*
+  \[ 4\] \.rela.dyn +.*
+  \[ 5\] \.rela.plt +.*
+  \[ 6\] \.plt +.*
+  \[ 7\] \.text +.*
+  \[ 8\] \.dynamic +.*
+  \[ 9\] \.got +.*
+  \[10\] \.got.plt +.*
+  \[11\] \.shstrtab +.*
+  \[12\] \.symtab +.*
+  \[13\] \.strtab +.*
+Key to Flags:
+.*
+.*
+.*
+
+Elf file type is DYN \(Shared object file\)
+Entry point 0x[0-9a-f]+
+There are [0-9]+ program headers, starting at offset [0-9]+
+
+Program Headers:
+  Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg Align
+  LOAD.*
+  LOAD.*
+  DYNAMIC.*
+
+ Section to Segment mapping:
+  Segment Sections...
+   00 +.hash .dynsym .dynstr .rela.dyn .rela.plt .plt .text *
+   01 +.dynamic .got .got.plt *
+   02 +.dynamic *
+
+Relocation section '.rela.dyn' at offset 0x[0-9a-f]+ contains 8 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+[0-9a-f]+  0+200000012 R_X86_64_TPOFF64 +0+ sG3 \+ 0
+[0-9a-f]+  0+300000012 R_X86_64_TPOFF64 +0+ sG5 \+ 0
+[0-9a-f]+  0+400000010 R_X86_64_DTPMOD64 +0+ sG2 \+ 0
+[0-9a-f]+  0+400000011 R_X86_64_DTPOFF64 +0+ sG2 \+ 0
+[0-9a-f]+  0+500000012 R_X86_64_TPOFF64 +0+ sG4 \+ 0
+[0-9a-f]+  0+800000012 R_X86_64_TPOFF64 +0+ sG6 \+ 0
+[0-9a-f]+  0+a00000010 R_X86_64_DTPMOD64 +0+ sG1 \+ 0
+[0-9a-f]+  0+a00000011 R_X86_64_DTPOFF64 +0+ sG1 \+ 0
+
+Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 3 entries:
+ +Offset +Info +Type +Symbol's Value  Symbol's Name \+ Addend
+[0-9a-f]+  0+600000007 R_X86_64_JUMP_SLOT +0+ __tls_get_addr \+ 0
+[0-9a-f]+  0+a00000024 R_X86_64_TLSDESC +0+ sG1 \+ 0
+[0-9a-f]+  0+400000024 R_X86_64_TLSDESC +0+ sG2 \+ 0
+
+Symbol table '.dynsym' contains 13 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_addr
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
+
+Symbol table '.symtab' contains 27 entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+ +[0-9]+: 0+ +0 NOTYPE  LOCAL  DEFAULT  UND *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +1 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +2 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +3 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +4 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +5 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +6 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +7 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +8 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +9 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +10 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +11 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +12 *
+ +[0-9]+: [0-9a-f]+ +0 SECTION LOCAL  DEFAULT +13 *
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _DYNAMIC
+ +[0-9]+: [0-9a-f]+ +0 OBJECT  LOCAL  HIDDEN  ABS _GLOBAL_OFFSET_TABLE_
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG3
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG5
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG2
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG4
+ +[0-9]+: 0+ +0 NOTYPE  GLOBAL DEFAULT  UND __tls_get_addr
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG6
+ +[0-9]+: [0-9a-f]+ +0 FUNC +GLOBAL DEFAULT +7 fc1
+ +[0-9]+: 0+ +0 TLS +GLOBAL DEFAULT  UND sG1
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _edata
+ +[0-9]+: [0-9a-f]+ +0 NOTYPE  GLOBAL DEFAULT  ABS _end
Index: ld/testsuite/ld-x86-64/tlsgdesc.s
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ld/testsuite/ld-x86-64/tlsgdesc.s	2006-01-13 18:14:55.000000000 -0500
@@ -0,0 +1,106 @@
+	.text
+	.globl	fc1
+	.type	fc1,@function
+fc1:
+	pushq	%rbp
+	movq	%rsp, %rbp
+	nop;nop;nop;nop
+
+	/* IE against global var.  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sG3@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* IE against global var.  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sG4@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* GD, gd first.  */
+	.byte	0x66
+	leaq	sG1@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	leaq	sG1@tlsdesc(%rip), %rax
+	call	*sG1@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD, desc first.  */
+	leaq	sG2@tlsdesc(%rip), %rax
+	call	*sG2@tlscall(%rax)
+	nop;nop;nop;nop
+
+	.byte	0x66
+	leaq	sG2@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE, gd first, after IE use.  */
+	.byte	0x66
+	leaq	sG3@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	leaq	sG3@tlsdesc(%rip), %rax
+	call	*sG3@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE, desc first, after IE use.  */
+	leaq	sG4@tlsdesc(%rip), %rax
+	call	*sG4@tlscall(%rax)
+	nop;nop;nop;nop
+
+	.byte	0x66
+	leaq	sG4@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* GD -> IE, gd first, before IE use.  */
+	.byte	0x66
+	leaq	sG5@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	leaq	sG5@tlsdesc(%rip), %rax
+	call	*sG5@tlscall(%rax)
+	nop;nop;nop;nop
+
+	/* GD -> IE, desc first, before IE use.  */
+	leaq	sG6@tlsdesc(%rip), %rax
+	call	*sG6@tlscall(%rax)
+	nop;nop;nop;nop
+
+	.byte	0x66
+	leaq	sG6@tlsgd(%rip), %rdi
+	.word	0x6666
+	rex64
+	call	__tls_get_addr@plt
+	nop;nop;nop;nop
+
+	/* IE against global var.  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sG5@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	/* IE against global var.  */
+	movq	%fs:0, %rcx
+	nop;nop
+	addq	sG6@gottpoff(%rip), %rcx
+	nop;nop;nop;nop
+
+	leave
+	ret
Index: ld/testsuite/ld-x86-64/x86-64.exp
===================================================================
--- ld/testsuite/ld-x86-64/x86-64.exp.orig	2006-01-13 18:13:26.000000000 -0500
+++ ld/testsuite/ld-x86-64/x86-64.exp	2006-01-13 18:14:55.000000000 -0500
@@ -1,5 +1,5 @@
 # Expect script for ld-x86_64 tests
-#   Copyright (C) 2002 Free Software Foundation
+#   Copyright (C) 2002, 2005 Free Software Foundation
 #
 # This file is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -39,6 +39,11 @@
      {{readelf -WSsrl tlspic.rd} {objdump -drj.text tlspic.dd}
       {objdump -sj.got tlspic.sd} {objdump -sj.tdata tlspic.td}}
       "libtlspic.so"}
+    {"TLS descriptor -fpic -shared transitions" "-shared -melf_x86_64"
+     "--64" {tlsdesc.s tlspic2.s}
+     {{readelf -WSsrld tlsdesc.rd} {objdump -drj.text tlsdesc.dd}
+      {objdump "-s -j.got -j.got.plt" tlsdesc.sd} {objdump -sj.tdata tlsdesc.td}
+      {objdump -drj.plt tlsdesc.pd}} "libtlsdesc.so"}
     {"Helper shared library" "-shared -melf_x86_64"
      "--64" {tlslib.s} {} "libtlslib.so"}
     {"TLS -fpic and -fno-pic exec transitions"
@@ -46,6 +51,15 @@
      {{readelf -WSsrl tlsbin.rd} {objdump -drj.text tlsbin.dd}
       {objdump -sj.got tlsbin.sd} {objdump -sj.tdata tlsbin.td}}
       "tlsbin"}
+    {"TLS descriptor -fpic and -fno-pic exec transitions"
+     "-melf_x86_64 tmpdir/libtlslib.so" "--64" {tlsbindesc.s tlsbin.s}
+     {{readelf -WSsrl tlsbindesc.rd} {objdump -drj.text tlsbindesc.dd}
+      {objdump -sj.got tlsbindesc.sd} {objdump -sj.tdata tlsbindesc.td}}
+      "tlsbindesc"}
+    {"TLS with global dynamic and descriptors"
+	"-shared -melf_x86_64" "--64" {tlsgdesc.s}
+     {{readelf -WSsrl tlsgdesc.rd} {objdump -drj.text tlsgdesc.dd}}
+      "libtlsgdesc.so"}
     {"TLS in debug sections" "-melf_x86_64"
      "--64" {tlsg.s}
      {{objdump -sj.debug_foobar tlsg.sd}} "tlsg"}

[-- Attachment #3: Type: text/plain, Size: 188 bytes --]


-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: RFC: TLS improvements for IA32 and AMD64/EM64T
  2006-01-14 17:58       ` Alexandre Oliva
@ 2006-01-18  1:45         ` Alan Modra
  0 siblings, 0 replies; 17+ messages in thread
From: Alan Modra @ 2006-01-18  1:45 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: binutils

On Sat, Jan 14, 2006 at 12:57:47PM -0500, Alexandre Oliva wrote:
> One more update.  This time I've modified a little bit the code
> generated to pad relaxations, to get the best performance according to
> my benchmarking (not a lot of difference, but still), and adjusted the
> testsuite to match.
> 
> Ok to install?

Yes, looks OK to me.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: RFC: TLS improvements for IA32 and AMD64/EM64T
  2006-10-10  8:23     ` Alexandre Oliva
@ 2006-10-10 16:24       ` Menezes, Evandro
  0 siblings, 0 replies; 17+ messages in thread
From: Menezes, Evandro @ 2006-10-10 16:24 UTC (permalink / raw)
  To: Alexandre Oliva
  Cc: Jan Beulich, Michael Matz, discuss, Andreas Jaeger, binutils,
	libc-alpha, Meissner, Michael, H. J. Lu

Oi, Alexandre. 

> > Would you consider adding the calculations for the new relocations
> > in order to improve their clarity?
> 
> I can try, although relaxations make it much trickier than it might
> seem.

Where possible.  If it gets too hairy, the text should spill the beans instead.
 
> > I remember some examples in your paper at the GCC Summit and adding
> > them to section 3.5 would be swell too.
> 
> So we're talking *really* self-contained, eh?  Fair enough, I'll take
> a shot.

I appreciate it.  It sure makes this psABI much more solid.  As is, it already refers to too many external ABIs, such as SY, i386 and C++, so I think that it exhausted its credit for external references. :-)
 
> > From your paper at the GCC Summit it's quite clear that such
> > additions to the psABI would be a fine idea.  Perhaps HJ would like
> > to consider the corresponding additions for the i386 psABI
> > extension.
> 
> H.J., do you have the i386 psABI in source form somewhere I could get
> it, to make the corresponding changes?

Actually, it's about an extension to the i386 psABI and it's an idea still in its infancy: http://sourceware.org/ml/binutils/2006-09/msg00342.html.

> > So, there's no question about the technical part of your proposal.
> > But, as you can infer from my comments above, I'd like to improve
> > the clarity of the psABI so that one wouldn't have to go to specific
> > implementations to figure out the details.  What do you think?
> 
> Sounds like a reasonable goal.
> 
> > -+referenced symbol binds locally, the \texttt{DTPOFF} may 
> be omitted.
> > ++referenced symbol binds locally, the relocations 
> \texttt{R_X86_64_64} and \texttt{R_X86_64_32} may be used instead.
> 
> No, in such cases the linker omits the relocation entirely, and fills
> the corresponding stop with the value it can compute itself.

Then how would you phrase it?

> If you'd rather install a patch with these minor modifications and
> keep the more detailed patch separate, let me know and I'll send you
> what I have right away.

That sounds like a fine idea.  As I haven't heard comments in contrary, there seems to be an unspoken agreement that it should be added.  Feel free to send the patch with minor changes and if we don't hear anything against it until the Oct 12 (GMT), I'll apply it.

Thank you,

-- 
_______________________________________________________
Evandro Menezes               AMD            Austin, TX



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: RFC: TLS improvements for IA32 and AMD64/EM64T
  2006-10-09 19:57   ` Menezes, Evandro
@ 2006-10-10  8:23     ` Alexandre Oliva
  2006-10-10 16:24       ` Menezes, Evandro
  0 siblings, 1 reply; 17+ messages in thread
From: Alexandre Oliva @ 2006-10-10  8:23 UTC (permalink / raw)
  To: Menezes, Evandro
  Cc: Jan Beulich, Michael Matz, discuss, Andreas Jaeger, binutils,
	libc-alpha, Michael Meissner, H. J. Lu

On Oct  9, 2006, "Menezes, Evandro" <evandro.menezes@amd.com> wrote:

> Would you consider adding the calculations for the new relocations
> in order to improve their clarity?

I can try, although relaxations make it much trickier than it might
seem.

> I remember some examples in your paper at the GCC Summit and adding
> them to section 3.5 would be swell too.

So we're talking *really* self-contained, eh?  Fair enough, I'll take
a shot.

> From your paper at the GCC Summit it's quite clear that such
> additions to the psABI would be a fine idea.  Perhaps HJ would like
> to consider the corresponding additions for the i386 psABI
> extension.

H.J., do you have the i386 psABI in source form somewhere I could get
it, to make the corresponding changes?

> So, there's no question about the technical part of your proposal.
> But, as you can infer from my comments above, I'd like to improve
> the clarity of the psABI so that one wouldn't have to go to specific
> implementations to figure out the details.  What do you think?

Sounds like a reasonable goal.

> -+referenced symbol binds locally, the \texttt{DTPOFF} may be omitted.
> ++referenced symbol binds locally, the relocations \texttt{R_X86_64_64} and \texttt{R_X86_64_32} may be used instead.

No, in such cases the linker omits the relocation entirely, and fills
the corresponding stop with the value it can compute itself.

>  +Otherwise, such relocations are always in pairs, such that the
> -+\texttt{DTPOFF64} relocation applies to the word64 right past the
> -+corresponding \texttt{DTPMOD} relocation.
> ++\texttt{R_X86_64_DTPOFF64} relocation applies to the word64 right past the
> ++corresponding \texttt{R_X86_64_DTPMOD64} relocation.

Ok, I've added R_X86_64_ everywhere I'd omitted it.

Please expect an updated patch soon.

If you'd rather install a patch with these minor modifications and
keep the more detailed patch separate, let me know and I'll send you
what I have right away.

-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Secretary for FSF Latin America        http://www.fsfla.org/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: RFC: TLS improvements for IA32 and AMD64/EM64T
  2006-10-08 20:53 ` Alexandre Oliva
  2006-10-09  6:23   ` Michael Matz
@ 2006-10-09 19:57   ` Menezes, Evandro
  2006-10-10  8:23     ` Alexandre Oliva
  1 sibling, 1 reply; 17+ messages in thread
From: Menezes, Evandro @ 2006-10-09 19:57 UTC (permalink / raw)
  To: Alexandre Oliva
  Cc: Jan Beulich, Michael Matz, discuss, Andreas Jaeger, binutils,
	libc-alpha, Michael Meissner, H. J. Lu

[-- Attachment #1: Type: text/plain, Size: 1646 bytes --]

Hi, Alexandre. 

> Here's an updated patch the should address all of your concerns.  The
> proposed ABI changes haven't changed at all for almost a year, and in
> the mean time we've ported it to one more platform (ARM), so I believe
> this is rock solid now.

It looks good and the patch is pretty informative.  However, there are some statements that may not be as clear as they could be, so I was thinking if the changes to your patch in attach seem reasonable.

Would you consider adding the calculations for the new relocations in order to improve their clarity?  The original paper on TLS goes on about them a bit, but it wouldn't be a bad idea to have the psABI document more stand-alone.

I remember some examples in your paper at the GCC Summit and adding them to section 3.5 would be swell too.

> Let me know what you think about the proposed changes.  They document
> what's implemented in GNU binutils, GCC and the pending patches I have
> for glibc, that I'm retesting after updating them to a current tree.

From your paper at the GCC Summit it's quite clear that such additions to the psABI would be a fine idea.  Perhaps HJ would like to consider the corresponding additions for the i386 psABI extension.

So, there's no question about the technical part of your proposal.  But, as you can infer from my comments above, I'd like to improve the clarity of the psABI so that one wouldn't have to go to specific implementations to figure out the details.  What do you think?

Thank you,

-- 
_______________________________________________________
Evandro Menezes               AMD            Austin, TX


[-- Attachment #2: tlsdesc.patch.patch --]
[-- Type: application/octet-stream, Size: 2048 bytes --]

--- tlsdesc.patch	2006-10-09 14:32:25.739161000 -0500
+++ tlsdesc.patch.new	2006-10-09 14:38:53.597399000 -0500
@@ -115,10 +115,10 @@ Index: object-files.tex
 +linker generates such relocations in adjacent entries in the GOT, in
 +response to \texttt{R_X86_64_TLSGD} and \texttt{R_X86_64_TLSLD}
 +relocations.  If the linker can compute the offset itself, because the
-+referenced symbol binds locally, the \texttt{DTPOFF} may be omitted.
++referenced symbol binds locally, the relocations \texttt{R_X86_64_64} and \texttt{R_X86_64_32} may be used instead.
 +Otherwise, such relocations are always in pairs, such that the
-+\texttt{DTPOFF64} relocation applies to the word64 right past the
-+corresponding \texttt{DTPMOD} relocation.
++\texttt{R_X86_64_DTPOFF64} relocation applies to the word64 right past the
++corresponding \texttt{R_X86_64_DTPMOD64} relocation.
  \end{sloppypar}
  
 +\texttt{R_X86_64_TPOFF64} and \texttt{R_X86_64_TPOFF32} resolve to the
@@ -129,12 +129,12 @@ Index: object-files.tex
 +
 +\texttt{R_X86_64_TLSGD} and \texttt{R_X86_64_TLSLD} both resolve to
 +PC-relative offsets to a \texttt{DTPMOD} GOT entry.  The difference
-+between them is that, for \texttt{TLSGD}, the following GOT entry will
++between them is that, for \texttt{R_X86_64_TLSGD}, the following GOT entry will
 +contain the offset of the referenced symbol into its TLS block,
-+whereas, for \texttt{TLSLD}, the following GOT entry will contain the
++whereas, for \texttt{R_X86_64_TLSLD}, the following GOT entry will contain the
 +offset for the base address of the TLS block.  The idea is that adding
-+this offset to the result of \texttt{DTPMOD32} for a symbol ought to
-+yield the same as the result of \texttt{DTPMOD64} for the same symbol.
++this offset to the result of \texttt{R_X86_64_DTPMOD32} for a symbol ought to
++yield the same as the result of \texttt{R_X86_64_DTPMOD64} for the same symbol.
 +
 +\texttt{R_X86_64_TLSDESC} resolves to a pair of word64s, called TLS
 +Descriptor, the first of which is a pointer to a function, followed by

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: RFC: TLS improvements for IA32 and AMD64/EM64T
  2006-10-08 20:53 ` Alexandre Oliva
@ 2006-10-09  6:23   ` Michael Matz
  2006-10-09 19:57   ` Menezes, Evandro
  1 sibling, 0 replies; 17+ messages in thread
From: Michael Matz @ 2006-10-09  6:23 UTC (permalink / raw)
  To: Alexandre Oliva
  Cc: Menezes, Evandro, Jan Beulich, discuss, Andreas Jaeger, binutils,
	libc-alpha

Hi Alexandre,

On Sun, 8 Oct 2006, Alexandre Oliva wrote:

> Here's an updated patch the should address all of your concerns.  The 
> proposed ABI changes haven't changed at all for almost a year, and in 
> the mean time we've ported it to one more platform (ARM), so I believe 
> this is rock solid now.

Thanks for the update.  From my perspective we should include it in the 
ABI document.  I'll wait a day or two in case there are concerns.


Ciao,
Michael. 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: RFC: TLS improvements for IA32 and AMD64/EM64T
  2005-09-19 23:18 Menezes, Evandro
@ 2006-10-08 20:53 ` Alexandre Oliva
  2006-10-09  6:23   ` Michael Matz
  2006-10-09 19:57   ` Menezes, Evandro
  0 siblings, 2 replies; 17+ messages in thread
From: Alexandre Oliva @ 2006-10-08 20:53 UTC (permalink / raw)
  To: Menezes, Evandro
  Cc: Jan Beulich, Michael Matz, discuss, Andreas Jaeger, binutils, libc-alpha

[-- Attachment #1: Type: text/plain, Size: 614 bytes --]

Hi, Evandro,

Sorry that it took so long for me to get back to you after the GCC
Summit.  I've been quite busy and couldn't focus on this issue for a
while.

Here's an updated patch the should address all of your concerns.  The
proposed ABI changes haven't changed at all for almost a year, and in
the mean time we've ported it to one more platform (ARM), so I believe
this is rock solid now.

Let me know what you think about the proposed changes.  They document
what's implemented in GNU binutils, GCC and the pending patches I have
for glibc, that I'm retesting after updating them to a current tree.

Thanks,


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: tlsdesc.patch --]
[-- Type: text/x-patch, Size: 8137 bytes --]

for ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* object-files.tex (Relocation Types): Add
	R_X86_64_GOTPC32_TLSDESC, R_X86_64_TLSDESC_CALL and
	R_X86_64_TLSDESC.  Add pointer to description.  Add short
	description of all TLS relocations.  Fix typo in DTPMOD64.
	* dl.tex (Procedure Linkage Table): Mention lazy relocation of TLS
	descriptors.  Add short description.

Index: dl.tex
===================================================================
--- dl.tex.orig	2006-10-08 16:53:13.000000000 -0300
+++ dl.tex	2006-10-08 17:39:44.000000000 -0300
@@ -265,6 +265,22 @@ evaluates procedure linkage table entrie
 resolution and relocation until the first execution of a table entry.
 \index{procedure linkage table|)}
 
+Relocation entries of type \codeindex{R_X86_64_TLSDESC} may also be
+subject to lazy relocation, using a single entry in the procedure
+linkage table and in the global offset table, at locations given by
+\texttt{DT_TLSDESC_PLT} and \texttt{DT_TLSDESC_GOT}, respectively, as
+described in ``Thread-Local Storage Descriptors for IA32 and
+AMD64/EM64T''\footnote{This document is currently available via
+  \url{http://people.redhat.com/aoliva/writeups/TLS/RFC-TLSDESC-x86.txt}}.
+
+For self-containment, \texttt{DT_TLSDESC_GOT} specifies a GOT entry in
+which the dynamic loader should store the address of its internal TLS
+Descriptor resolver function, whereas \texttt{DT_TLSDESC_PLT}
+specifies the address of a PLT entry to be used as the TLS descriptor
+resolver function for lazy resolution from within this module.  The
+PLT entry must push the linkmap of the module onto the stack and
+tail-call the internal TLS Descriptor resolver function.
+
 \subsubsection{Large Models}
 
 In the small and medium code models the size of both the PLT and the GOT
Index: object-files.tex
===================================================================
--- object-files.tex.orig	2006-10-08 16:53:13.000000000 -0300
+++ object-files.tex	2006-10-08 17:46:49.000000000 -0300
@@ -435,7 +435,7 @@ the relocation addend.
       \texttt{R_X86_64_PC16}  & 13 & \textit{word16} & \texttt{S + A - P} \\
       \texttt{R_X86_64_8}     & 14 & \textit{word8} & \texttt{S + A} \\
       \texttt{R_X86_64_PC8}   & 15 & \textit{word8} & \texttt{S + A - P} \\
-      \texttt{R_X86_64_DPTMOD64}   & 16 & \textit{word64} &  \\
+      \texttt{R_X86_64_DTPMOD64}   & 16 & \textit{word64} &  \\
       \texttt{R_X86_64_DTPOFF64}   & 17 & \textit{word64} &  \\
       \texttt{R_X86_64_TPOFF64}   & 18 & \textit{word64} &  \\
       \texttt{R_X86_64_TLSGD}   & 19 & \textit{word32} &  \\
@@ -448,6 +448,9 @@ the relocation addend.
       \texttt{R_X86_64_GOTPC32} & 26 & \textit{word32} & \texttt{GOT + A - P} \\
       \texttt{R_X86_64_SIZE32} & 32 & \textit{word32} & \texttt{Z + A} \\
       \texttt{R_X86_64_SIZE64} & 33 & \textit{word64} & \texttt{Z + A} \\
+      \texttt{R_X86_64_GOTPC32_TLSDESC} & 34 & \textit{word32} &  \\
+      \texttt{R_X86_64_TLSDESC_CALL} & 35 & none &  \\
+      \texttt{R_X86_64_TLSDESC} & 36 & \textit{word64}$\times 2$ & \\
 %      \texttt{R_X86_64_GOT64} & 16 & \textit{word64} & \texttt{G + A} \\
 %      \texttt{R_X86_64_PLT64} & 17 & \textit{word64} & \texttt{L + A - P} \\
     \end{tabular}
@@ -469,6 +472,7 @@ to those used for the \intelabi.  \footn
   loading the offset into a displacement register; the base plus
   immediate displacement addressing form can be used.}
 
+\begin{sloppypar}
 The \texttt{R_X86_64_GOTPCREL} relocation has different semantics from the
 \texttt{R_X86_64_GOT32} or equivalent i386 \texttt{R_I386_GOTPC} relocation.
 In particular, because the \xARCH architecture has an addressing mode relative
@@ -477,6 +481,7 @@ using a single instruction.  The calcula
 \texttt{R_X86_64_GOTPCREL} relocation gives the difference between the location
 in the GOT where the symbol's address is given and the location where the
 relocation is applied.
+\end{sloppypar}
 
 \begin{sloppypar}
 The \texttt{R_X86_64_32} and \texttt{R_X86_64_32S} relocations truncate
@@ -492,19 +497,72 @@ relocations is not conformant to this AB
 added for documentation purposes.  The \texttt{R_X86_64_16}, and
 \texttt{R_X86_64_8} relocations truncate the computed value to 16-bits
 resp. 8-bits.
+\end{sloppypar}
 
-The relocations \texttt{R_X86_64_DPTMOD64},
-\texttt{R_X86_64_DTPOFF64}, \texttt{R_X86_64_TPOFF64} ,
-\texttt{R_X86_64_TLSGD} , \texttt{R_X86_64_TLSLD} ,
+\begin{sloppypar}
+The relocations \texttt{R_X86_64_DTPMOD64},
+\texttt{R_X86_64_DTPOFF64}, \texttt{R_X86_64_TPOFF64},
+\texttt{R_X86_64_TLSGD}, \texttt{R_X86_64_TLSLD},
 \texttt{R_X86_64_DTPOFF32}, \texttt{R_X86_64_GOTTPOFF} and
 \texttt{R_X86_64_TPOFF32} are listed for completeness.  They are part
 of the Thread-Local Storage ABI extensions and are documented in the
 document called ``ELF Handling for Thread-Local
 Storage''\footnote{This document is currently available via
-  \url{http://people.redhat.com/drepper/tls.pdf}}\index{Thread-Local Storage}.
+  \url{http://people.redhat.com/drepper/tls.pdf}}\index{Thread-Local
+  Storage}.  The relocations \texttt{R_X86_64_GOTPC32_TLSDESC},
+\texttt{R_X86_64_TLSDESC_CALL} and \texttt{R_X86_64_TLSDESC} are also
+used for Thread-Local Storage, but are not documented there as of this
+writing.  A description can be found in the document ``Thread-Local
+Storage Descriptors for IA32 and AMD64/EM64T''\footnote{This document
+  is currently available via
+  \url{http://people.redhat.com/aoliva/writeups/TLS/RFC-TLSDESC-x86.txt}}.
+\end{sloppypar}
+
+In order to make this document self-contained, a description of the
+TLS relocations follows.
 
+\begin{sloppypar}
+\texttt{R_X86_64_DTPMOD64} resolves to the index of the dynamic thread
+vector entry that points to the base address of the TLS block
+corresponding to the module that defines the referenced symbol.
+\texttt{R_X86_64_DTPOFF64} and \texttt{R_X86_64_DTPOFF32} compute the
+offset from the pointer in that entry to the referenced symbol.  The
+linker generates such relocations in adjacent entries in the GOT, in
+response to \texttt{R_X86_64_TLSGD} and \texttt{R_X86_64_TLSLD}
+relocations.  If the linker can compute the offset itself, because the
+referenced symbol binds locally, the \texttt{DTPOFF} may be omitted.
+Otherwise, such relocations are always in pairs, such that the
+\texttt{DTPOFF64} relocation applies to the word64 right past the
+corresponding \texttt{DTPMOD} relocation.
 \end{sloppypar}
 
+\texttt{R_X86_64_TPOFF64} and \texttt{R_X86_64_TPOFF32} resolve to the
+offset from the thread pointer to a thread-local variable.  The former
+is generated in response to \texttt{R_X86_64_GOTTPOFF}, that resolves
+to a PC-relative address of a GOT entry containing such a 64-bit
+offset.
+
+\texttt{R_X86_64_TLSGD} and \texttt{R_X86_64_TLSLD} both resolve to
+PC-relative offsets to a \texttt{DTPMOD} GOT entry.  The difference
+between them is that, for \texttt{TLSGD}, the following GOT entry will
+contain the offset of the referenced symbol into its TLS block,
+whereas, for \texttt{TLSLD}, the following GOT entry will contain the
+offset for the base address of the TLS block.  The idea is that adding
+this offset to the result of \texttt{DTPMOD32} for a symbol ought to
+yield the same as the result of \texttt{DTPMOD64} for the same symbol.
+
+\texttt{R_X86_64_TLSDESC} resolves to a pair of word64s, called TLS
+Descriptor, the first of which is a pointer to a function, followed by
+an argument.  The function is passed a pointer to the this pair of
+entries in \%rax and, using the argument in the second entry, it must
+compute and return in \%rax the offset from the thread pointer to the
+symbol referenced in the relocation, without modifying any registers
+other than processor flags.  \texttt{R_X86_64_GOTPC32_TLSDESC}
+resolves to the PC-relative address of a TLS descriptor corresponding
+to the named symbol.  \texttt{R_X86_64_TLSDESC_CALL} must annotate the
+instruction used to call the TLS Descriptor resolver function, so as
+to enable relaxation of that instruction.
+
 \subsection{Large Models}
 
 In order to extend both the PLT and the GOT beyond 2GB, it

[-- Attachment #3: Type: text/plain, Size: 1971 bytes --]



On Sep 19, 2005, "Menezes, Evandro" <evandro.menezes@amd.com> wrote:

> Alexandre, 
>> Please read the document referenced in the patch, for 
>> starters.  In it you'll see the exact spelling of the coding 
>> samples is not final yet, and it doesn't make sense to 
>> maintain yet another copy of this until it settles down.  

> When it does, it'll be added to the ABI then.  Not before.  For now, it's OK to reserve the relocation numbers in this mailing list.  

>> Also, you'll find that the calculations are not quite 
>> possible to express in the way other relocations are 
>> expressed; suggestions are welcome.  

> State so, perhaps in a note, expanding what they mean.

>> Finally, what's wrong 
>> with following the existing practice of referring to TLS 
>> specs elsewhere?

> The intent is that the x86-64 ABI remains a stand-alone document as much as possible.  It's not quite there yet, but adding yet another external reference sets it back even further.

> BTW, the TLS reference is slated to be incorporated into the x86-64 ABI.

>> The point of this posting was more to reserve the relocation 
>> numbers for these purposes (the purpose of the relocations is 
>> quite solid already, even though the numbers have changed as 
>> recently as yesterday), but I'm yet to do some more 
>> performance tests with some minor variations of the code 
>> sequences to choose the best one.  I don't want to have to 
>> maintain all this information in sync between multiple specs 
>> documents and the several different packages that implement 
>> them; having a single specs document is much better for now.

> That's fine.  When it reaches a mature state, patches against the ABI will be more than welcome.

-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Secretary for FSF Latin America        http://www.fsfla.org/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: RFC: TLS improvements for IA32 and AMD64/EM64T
@ 2005-09-19 23:18 Menezes, Evandro
  2006-10-08 20:53 ` Alexandre Oliva
  0 siblings, 1 reply; 17+ messages in thread
From: Menezes, Evandro @ 2005-09-19 23:18 UTC (permalink / raw)
  To: Alexandre Oliva
  Cc: Jan Beulich, Michael Matz, discuss, Andreas Jaeger, binutils, libc-alpha

Alexandre, 

> Please read the document referenced in the patch, for 
> starters.  In it you'll see the exact spelling of the coding 
> samples is not final yet, and it doesn't make sense to 
> maintain yet another copy of this until it settles down.  

When it does, it'll be added to the ABI then.  Not before.  For now, it's OK to reserve the relocation numbers in this mailing list.  

> Also, you'll find that the calculations are not quite 
> possible to express in the way other relocations are 
> expressed; suggestions are welcome.  

State so, perhaps in a note, expanding what they mean.

> Finally, what's wrong 
> with following the existing practice of referring to TLS 
> specs elsewhere?

The intent is that the x86-64 ABI remains a stand-alone document as much as possible.  It's not quite there yet, but adding yet another external reference sets it back even further.

BTW, the TLS reference is slated to be incorporated into the x86-64 ABI.

> The point of this posting was more to reserve the relocation 
> numbers for these purposes (the purpose of the relocations is 
> quite solid already, even though the numbers have changed as 
> recently as yesterday), but I'm yet to do some more 
> performance tests with some minor variations of the code 
> sequences to choose the best one.  I don't want to have to 
> maintain all this information in sync between multiple specs 
> documents and the several different packages that implement 
> them; having a single specs document is much better for now.

That's fine.  When it reaches a mature state, patches against the ABI will be more than welcome.

Thanks,

_______________________________________________________
Evandro Menezes                          GNU Tools Team
512-602-9940                                        AMD
evandro.menezes@amd.com                      Austin, TX

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: RFC: TLS improvements for IA32 and AMD64/EM64T
  2005-09-17 14:14 Menezes, Evandro
@ 2005-09-17 18:45 ` Alexandre Oliva
  0 siblings, 0 replies; 17+ messages in thread
From: Alexandre Oliva @ 2005-09-17 18:45 UTC (permalink / raw)
  To: Menezes, Evandro
  Cc: Jan Beulich, Michael Matz, discuss, Andreas Jaeger, binutils, libc-alpha

On Sep 16, 2005, "Menezes, Evandro" <evandro.menezes@amd.com> wrote:

> Alexandre, 
>> Here's a patch for the x86-64 ABI document that adds the new 
>> relocations and references the new dynamic table numbers, 
>> referring to the latest version of my specs on the web for details.

> Please add the respective calculations and coding examples.

Please read the document referenced in the patch, for starters.  In it
you'll see the exact spelling of the coding samples is not final yet,
and it doesn't make sense to maintain yet another copy of this until
it settles down.  Also, you'll find that the calculations are not
quite possible to express in the way other relocations are expressed;
suggestions are welcome.  Finally, what's wrong with following the
existing practice of referring to TLS specs elsewhere?

The point of this posting was more to reserve the relocation numbers
for these purposes (the purpose of the relocations is quite solid
already, even though the numbers have changed as recently as
yesterday), but I'm yet to do some more performance tests with some
minor variations of the code sequences to choose the best one.  I
don't want to have to maintain all this information in sync between
multiple specs documents and the several different packages that
implement them; having a single specs document is much better for now.

Thanks for your, ehrm, valuable feedback :-/

-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: RFC: TLS improvements for IA32 and AMD64/EM64T
@ 2005-09-17 14:14 Menezes, Evandro
  2005-09-17 18:45 ` Alexandre Oliva
  0 siblings, 1 reply; 17+ messages in thread
From: Menezes, Evandro @ 2005-09-17 14:14 UTC (permalink / raw)
  To: Alexandre Oliva, Jan Beulich, Michael Matz, discuss
  Cc: Andreas Jaeger, binutils, libc-alpha

Alexandre, 

> Here's a patch for the x86-64 ABI document that adds the new 
> relocations and references the new dynamic table numbers, 
> referring to the latest version of my specs on the web for details.

Please add the respective calculations and coding examples.

Thanks,

_______________________________________________________
Evandro Menezes                          GNU Tools Team
512-602-9940                                        AMD
evandro.menezes@amd.com                      Austin, TX

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2006-10-10 16:24 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-09-16  6:07 RFC: TLS improvements for IA32 and AMD64/EM64T Alexandre Oliva
2005-09-16  7:27 ` Alexandre Oliva
2005-09-16  7:34   ` Andreas Jaeger
2005-09-16  8:19     ` Jan Beulich
2005-09-16 21:01       ` Alexandre Oliva
2005-09-18 17:17   ` Alexandre Oliva
2005-09-22  7:53     ` Alexandre Oliva
2006-01-14 17:58       ` Alexandre Oliva
2006-01-18  1:45         ` Alan Modra
2005-09-17 14:14 Menezes, Evandro
2005-09-17 18:45 ` Alexandre Oliva
2005-09-19 23:18 Menezes, Evandro
2006-10-08 20:53 ` Alexandre Oliva
2006-10-09  6:23   ` Michael Matz
2006-10-09 19:57   ` Menezes, Evandro
2006-10-10  8:23     ` Alexandre Oliva
2006-10-10 16:24       ` Menezes, Evandro

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).