Re: GDB support for thread-local storage

Jim Blandy
2002-06-21T19:34:30Z

Andrew Cagney <ac131313@cygnus.com> writes:
> > I've posted a note to the Dwarf mailing list, describing the
> > DW_OP_push_tls_address approach, and saying that we'll experiment with
> > this as a GNU extension to Dwarf and write back when we've actually
> > got something working.
>
> Hmm, would you be able to post the prososal here?

Sure thing. (I re-used most of the language in the Dwarf proposal in
the message you replied to, so you've seen almost all of it already.)

Something to make clear, though --- this isn't a "proposal" proper.
The way the Dwarf committee operates (or the way I think it should
operate, and thus the way I try to deal with it) is:

- you float an idea by them for general approval;
- then you go off and implement it as a vendor extension;
- then once you've got it actually working you come back and make it a
real proposal;
- if it's accepted you get assigned proper numbers (not in the vendor
extension range) for your attribute tags, die tags, and so on;
- and finally you switch your emitter to recognize the real numbers.

So this is in the "float an idea by them" stage. Very preliminary.

$Id: dwarf,v 1.4 2002/06/12 21:44:14 jimb Exp $

(The function of DW_OP_push_tls_address is similar to that of the
run-time function __get_tls_addr, so it was tempting to name the
operation DW_OP_get_tls_addr. However, DW_OP_push_tls_address is more
consistent with the names of the other operations, especially
DW_OP_push_object_address.)

To section 2.4.1.3, "Stack Operations", add the following paragraphs
after DW_OP_push_object_address:

12. DW_OP_push_tls_address

The DW_OP_push_tls_address operation pushes the base address of the
current thread's thread-local storage block. If the expression occurs
in the Dwarf information for a dynamically loaded library, then
DW_OP_push_tls_address pushes the base address of that library's block
for the current thread. If the library's storage for the current
thread has not yet been allocated, a Dwarf consumer may arrange for it
to be allocated now, or report an error to the user.

<rationale italics>
Some implementations of C and C++ support a ``__thread'' storage
class, for variables that occupy distinct memory in distinct threads.
For example, the definition:

__thread int foo;

declares an integer variable named ``foo'' which has a separate value
and address in each thread, much as a variable declared ``auto'' has a
separate value and address in each invocation of the function
containing its declaration. Creating a new thread creates a new
instance of ``foo'', and when the thread exits, the storage for
``foo'' is freed.

Typically, a program includes an ``initialization image'' --- a block
of memory containing the initial values for any thread-local variables
it defines. When the program creates a new thread, the run-time
system allocates a fresh block of memory for those thread-local
variables, and copies the initialization image into it to give the
variables their initialized values.

A dynamically loaded library may also define thread-local variables.
Some implementations delay allocating memory for such variables until
the thread actually refers to them for the first time. This avoids
the overhead of allocating and initializing the library's thread-local
storage for all the threads present in a program when the library is
loaded, even though only a few threads might actually use the library.

However, when an implementation allocates thread-local storage on
demand, this makes it hard to describe the location of a thread-local
variable using ordinary Dwarf expressions: referencing the storage may
entail allocating memory, copying an initialization image into place,
registering it with the thread, and so on. A dedicated operation like
DW_OP_push_tls_address leaves this complicated task to the debugger,
which is presumably already familiar with the program's ABI and thread
system, and can handle the request appropriately.
</rationale italics>