--- ./gdb/Makefile.in 2008-03-17 13:15:08.000000000 +0100 +++ ./gdb/Makefile.in 2008-12-02 16:04:02.000000000 +0100 @@ -2104,7 +2104,7 @@ f-exp.o: f-exp.c $(defs_h) $(gdb_string_ findvar.o: findvar.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(frame_h) \ $(value_h) $(gdbcore_h) $(inferior_h) $(target_h) $(gdb_string_h) \ $(gdb_assert_h) $(floatformat_h) $(symfile_h) $(regcache_h) \ - $(user_regs_h) $(block_h) + $(user_regs_h) $(block_h) $(objfiles_h) f-lang.o: f-lang.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \ $(expression_h) $(parser_defs_h) $(language_h) $(f_lang_h) \ $(valprint_h) $(value_h) --- ./gdb/findvar.c 2008-01-01 23:53:09.000000000 +0100 +++ ./gdb/findvar.c 2008-12-02 16:03:49.000000000 +0100 @@ -34,6 +34,7 @@ #include "regcache.h" #include "user-regs.h" #include "block.h" +#include "objfiles.h" /* Basic byte-swapping routines. GDB has needed these for a long time... All extract a target-format integer at ADDR which is LEN bytes long. */ @@ -559,6 +560,7 @@ addresses have not been bound by the dyn case LOC_UNRESOLVED: { struct minimal_symbol *msym; + asection *section; msym = lookup_minimal_symbol (DEPRECATED_SYMBOL_NAME (var), NULL, NULL); if (msym == NULL) @@ -568,6 +570,19 @@ addresses have not been bound by the dyn SYMBOL_BFD_SECTION (msym)); else addr = SYMBOL_VALUE_ADDRESS (msym); + + section = SYMBOL_BFD_SECTION (msym); + if (section && (section->flags & SEC_THREAD_LOCAL) != 0) + { + struct objfile *objfile; + + ALL_OBJFILES (objfile) + if (objfile->obfd == section->owner) + { + addr = target_translate_tls_address (objfile, addr); + break; + } + } } break; --- ./gdb/printcmd.c 2008-01-30 20:19:51.000000000 +0100 +++ ./gdb/printcmd.c 2008-12-02 16:05:51.000000000 +0100 @@ -1219,15 +1219,32 @@ address_info (char *exp, int from_tty) else { section = SYMBOL_BFD_SECTION (msym); - printf_filtered (_("static storage at address ")); load_addr = SYMBOL_VALUE_ADDRESS (msym); - fputs_filtered (paddress (load_addr), gdb_stdout); - if (section_is_overlay (section)) + + if (section && (section->flags & SEC_THREAD_LOCAL) != 0) + { + struct objfile *objfile; + + ALL_OBJFILES (objfile) + if (objfile->obfd == section->owner) + { + printf_filtered (_("a thread-local variable at offset %s " + "in the thread-local storage for `%s'"), + paddr_nz (load_addr), objfile->name); + break; + } + } + else { - load_addr = overlay_unmapped_address (load_addr, section); - printf_filtered (_(",\n -- loaded at ")); + printf_filtered (_("static storage at address ")); fputs_filtered (paddress (load_addr), gdb_stdout); - printf_filtered (_(" in overlay section %s"), section->name); + if (section_is_overlay (section)) + { + load_addr = overlay_unmapped_address (load_addr, section); + printf_filtered (_(",\n -- loaded at ")); + fputs_filtered (paddress (load_addr), gdb_stdout); + printf_filtered (_(" in overlay section %s"), section->name); + } } } } --- ./gdb/testsuite/gdb.threads/tls.c 2003-07-29 23:51:25.000000000 +0200 +++ ./gdb/testsuite/gdb.threads/tls.c 2008-12-02 15:56:48.000000000 +0100 @@ -20,6 +20,9 @@ __thread int a_thread_local; __thread int another_thread_local; +/* psymtabs->symtabs resolving check. */ +extern __thread int file2_thread_local; + /* Global variable just for info addr in gdb. */ int a_global; @@ -119,6 +122,12 @@ void *spin( vp ) } void +function_referencing_file2_thread_local (void) +{ + file2_thread_local = file2_thread_local; +} + +void do_pass() { int i; --- ./gdb/testsuite/gdb.threads/tls.exp 2008-01-01 23:53:22.000000000 +0100 +++ ./gdb/testsuite/gdb.threads/tls.exp 2008-12-02 15:56:48.000000000 +0100 @@ -18,7 +18,9 @@ # bug-gdb@prep.ai.mit.edu set testfile tls +set testfile2 tls2 set srcfile ${testfile}.c +set srcfile2 ${testfile2}.c set binfile ${objdir}/${subdir}/${testfile} if [istarget "*-*-linux"] then { @@ -27,7 +29,7 @@ if [istarget "*-*-linux"] then { set target_cflags "" } -if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile} ${srcdir}/${subdir}/${srcfile2}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } { return -1 } @@ -287,6 +289,20 @@ gdb_test "info address a_global" \ setup_kfail "gdb/1294" "*-*-*" gdb_test "info address me" ".*me.*is a variable at offset.*" "info address me" + +# Test LOC_UNRESOLVED references resolving for `extern' TLS variables. + +gdb_test "p a_thread_local" " = \[0-9\]+" +# Here it could crash with: Cannot access memory at address 0x0 +gdb_test "p file2_thread_local" " = \[0-9\]+" +# Depending on the current lookup scope we get LOC_UNRESOLVED or LOC_COMPUTED +# both printing: +# Symbol "file2_thread_local" is a thread-local variable at offset 8 in the thread-local storage for `.../gdb.threads/tls'. +gdb_test "info address file2_thread_local" "Symbol \"file2_thread_local\" is a thread-local variable.*" +# Here it could also crash with: Cannot access memory at address 0x0 +gdb_test "p a_thread_local" " = \[0-9\]+" "p a_thread_local second time" +gdb_test "info address a_thread_local" "Symbol \"a_thread_local\" is a thread-local variable.*" + # Done! # gdb_exit --- ./gdb/testsuite/gdb.threads/tls2.c 1970-01-01 01:00:00.000000000 +0100 +++ ./gdb/testsuite/gdb.threads/tls2.c 2008-12-02 15:56:48.000000000 +0100 @@ -0,0 +1,28 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2008 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Please email any bugs, comments, and/or additions to this file to: + bug-gdb@prep.ai.mit.edu */ + +extern __thread int a_thread_local; +__thread int file2_thread_local; + +void +function_referencing_a_thread_local (void) +{ + a_thread_local = a_thread_local; +}