Bug 9384 - GDB can't find __thread variable in C++ program
Summary: GDB can't find __thread variable in C++ program
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: symtab (show other bugs)
Version: unknown
: P3 enhancement
Target Milestone: 7.2
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks: 14421
  Show dependency treegraph
 
Reported: 2007-06-26 23:48 UTC by Jim Blandy
Modified: 2012-07-31 09:46 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jim Blandy 2007-06-26 23:48:01 UTC
[Converted from Gnats 2279]

See how-to-repeat.

GDB seems to create two symbol table entries for 'i', one with LOC_UNRESOLVED and one with LOC_COMPUTED; it doesn't recognize that the first die is just a specification for the second.

If you remove the __thread qualifier, GDB still creates the two symtab entries, but can print its value.  I think this is because GDB tries to handle LOC_UNRESOLVED symbols by falling back to the minsyms, but in the TLS case the minsym's value is the variable's TLS offset.

So there may be two bugs to fix here:
- dwarf2read shouldn't be creating two symtab entries for 'i'.
- the LOC_UNRESOLVED fallback code shouldn't try to use STT_TLS minsym values as addresses.

Release:
unknown

Environment:
Fedora Core 6, IA32

How-To-Repeat:
$ cat tls.c
__thread int i;

int
main (int argc, char **argv)
{
  i = 5;
  return i;
}
$ g++ -g tls.c -o tls -lpthread
$ readelf -d tls

Dynamic section at offset 0x508 contains 24 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libpthread.so.0]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libm.so.6]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x0000000c (INIT)                       0x80482fc
 0x0000000d (FINI)                       0x80484c8
 0x6ffffef5 (GNU_HASH)                   0x8048168
 0x00000005 (STRTAB)                     0x80481e8
 0x00000006 (SYMTAB)                     0x8048188
 0x0000000a (STRSZ)                      176 (bytes)
 0x0000000b (SYMENT)                     16 (bytes)
 0x00000015 (DEBUG)                      0x0
 0x00000003 (PLTGOT)                     0x80495f4
 0x00000002 (PLTRELSZ)                   16 (bytes)
 0x00000014 (PLTREL)                     REL
 0x00000017 (JMPREL)                     0x80482ec
 0x00000011 (REL)                        0x80482e4
 0x00000012 (RELSZ)                      8 (bytes)
 0x00000013 (RELENT)                     8 (bytes)
 0x6ffffffe (VERNEED)                    0x80482a4
 0x6fffffff (VERNEEDNUM)                 2
 0x6ffffff0 (VERSYM)                     0x8048298
 0x00000000 (NULL)                       0x0
$ ~/gdb/pub/bin/gdb tls
GNU gdb 6.6.50.20070625-cvs
Copyright (C) 2007 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) start
Breakpoint 1 at 0x8048402: file tls.c, line 6.
Starting program: /home/jimb/play/tls 
[Thread debugging using libthread_db enabled]
[New Thread 0xb7feb6d0 (LWP 9387)]
[Switching to Thread 0xb7feb6d0 (LWP 9387)]
main () at tls.c:6
6         i = 5;
Current language:  auto; currently c++
(gdb) print i
Cannot access memory at address 0x0
(gdb) quit
The program is running.  Exit anyway? (y or n) y
$ readelf -wi tls
The section .debug_info contains:

  Compilation Unit @ offset 0x0:
   Length:        201
   Version:       2
   Abbrev Offset: 0
   Pointer Size:  4
 <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
     DW_AT_stmt_list   : 0
     DW_AT_high_pc     : 0x8048419
     DW_AT_low_pc      : 0x80483f4
     DW_AT_producer    : GNU C++ 4.1.1 20070105 (Red Hat 4.1.1-51)
     DW_AT_language    : 4      (C++)
     DW_AT_name        : tls.c
     DW_AT_comp_dir    : /home/jimb/play
 <1><59>: Abbrev Number: 2 (DW_TAG_subprogram)
     DW_AT_sibling     : <8f>
     DW_AT_external    : 1
     DW_AT_name        : main
     DW_AT_decl_file   : 1
     DW_AT_decl_line   : 4
     DW_AT_type        : <8f>
     DW_AT_low_pc      : 0x80483f4
     DW_AT_high_pc     : 0x8048419
     DW_AT_frame_base  : 0      (location list)
 <2><76>: Abbrev Number: 3 (DW_TAG_formal_parameter)
     DW_AT_name        : argc
     DW_AT_decl_file   : 1
     DW_AT_decl_line   : 4
     DW_AT_type        : <8f>
 <2><82>: Abbrev Number: 3 (DW_TAG_formal_parameter)
     DW_AT_name        : argv
     DW_AT_decl_file   : 1
     DW_AT_decl_line   : 4
     DW_AT_type        : <96>
 <1><8f>: Abbrev Number: 4 (DW_TAG_base_type)
     DW_AT_name        : int
     DW_AT_byte_size   : 4
     DW_AT_encoding    : 5      (signed)
 <1><96>: Abbrev Number: 5 (DW_TAG_pointer_type)
     DW_AT_byte_size   : 4
     DW_AT_type        : <9c>
 <1><9c>: Abbrev Number: 5 (DW_TAG_pointer_type)
     DW_AT_byte_size   : 4
     DW_AT_type        : <a2>
 <1><a2>: Abbrev Number: 4 (DW_TAG_base_type)
     DW_AT_name        : char
     DW_AT_byte_size   : 1
     DW_AT_encoding    : 6      (signed char)
 <1><aa>: Abbrev Number: 6 (DW_TAG_namespace)
     DW_AT_sibling     : <c0>
     DW_AT_name        : ::
     DW_AT_decl_file   : 2
     DW_AT_decl_line   : 0
 <2><b4>: Abbrev Number: 7 (DW_TAG_variable)
     DW_AT_name        : i
     DW_AT_decl_file   : 1
     DW_AT_decl_line   : 1
     DW_AT_type        : <8f>
     DW_AT_external    : 1
     DW_AT_declaration : 1
 <1><c0>: Abbrev Number: 8 (DW_TAG_variable)
     DW_AT_specification: <b4>
     DW_AT_location    : 6 byte block: 3 0 0 0 0 e0     (DW_OP_addr: 0; DW_OP_GNU_push_tls_address)

$
Comment 1 Jan Kratochvil 2009-04-13 16:10:44 UTC
It started working on post-6.8 GDB but it is not completely correct as it works
through the .symtab TLS resolving now.

http://sourceware.org/ml/gdb/2009-04/msg00100.html =>

Checked the difference, both g++-4.3 and gcc-4.1 use more simple format as
read by `readelf -wi':
 <1><88>: Abbrev Number: 7 (DW_TAG_variable)
    <89>   DW_AT_name        : i	
[snip]
    <91>   DW_AT_external    : 1	
    <92>   DW_AT_location    : 10 byte block: 3 0 0 0 0 0 0 0 0 e0 	(DW_OP_addr:
0; DW_OP_GNU_push_tls_address or DW_OP_HP_unknown)

while g++-4.1 uses:
 <2><d2>: Abbrev Number: 7 (DW_TAG_variable)
     DW_AT_name        : i	
[snip]
     DW_AT_external    : 1	
     DW_AT_declaration : 1	
 <1><de>: Abbrev Number: 8 (DW_TAG_variable)
     DW_AT_specification: <d2>	
     DW_AT_location    : 10 byte block: 3 0 0 0 0 0 0 0 0 e0 	(DW_OP_addr: 0;
DW_OP_GNU_push_tls_address)

Which is perfectly valid DWARF but current GDB cannot cope with it.

It starts working in post-6.8 FSF GDB because it gets resolved as an external
TLS reference.  External TLS references did not work before.  It is not
completely correct but in practice it works.  Fixed by this patch:
http://sourceware.org/ml/gdb/2008-07/threads.html#00341
http://sourceware.org/ml/gdb-patches/2008-08/threads.html#00026
http://sourceware.org/ml/gdb-patches/2008-09/threads.html#00204
http://sourceware.org/ml/gdb-patches/2008-11/threads.html#00706
http://sourceware.org/ml/gdb-patches/2008-12/threads.html#00003
http://sourceware.org/ml/gdb-cvs/2008-12/msg00009.html
Comment 2 Tom Tromey 2010-07-13 17:05:26 UTC
I think the TLS support works fine now.