ba67a7996c
- Fix attach to stopped process, supersede `gdb-6.3-attach-stop-20051011.patch'. - Fix TLS symbols resolving for objects with separate .debug file (-debuginfo). - Fix TLS symbols resolving for shared libraries with a relative pathname. - Support TLS symbols (+`errno' suggestion if no pthread is found) (BZ 185337).
826 lines
29 KiB
Diff
826 lines
29 KiB
Diff
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=185337
|
||
|
||
|
||
currently for trivia nonthreaded helloworld with no debug info up to -ggdb2 you
|
||
will get:
|
||
(gdb) p errno
|
||
Cannot access memory at address 0x8
|
||
|
||
* with -ggdb3 "errno" gets resolved as _macro_ and the resulting
|
||
"(*__errno_location ())" expression is always fine.
|
||
|
||
* with -ggdb2 and less "errno" in fact does not exist anywhere as it was
|
||
compiled to "(*__errno_location ())" and the macro definition is not present.
|
||
Unfortunately gdb will find the TLS symbol and it will try to access it but
|
||
as the program has been compiled without -lpthread the TLS base register
|
||
(%gs on i386) is not setup and it will result in:
|
||
Cannot access memory at address 0x8
|
||
|
||
IMO the right way is to ignore TLS symbols for inferiors without activated
|
||
threading. Patch attached.
|
||
|
||
Also attached suggestion patch how to deal with the most common "errno" symbol
|
||
for the most common under-ggdb3 compiled programs.
|
||
|
||
|
||
2006-08-25 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||
|
||
* dwarf2loc.c (dwarf_expr_tls_address): Code moved out to
|
||
`target_translate_tls_address'.
|
||
* target.c (target_translate_tls_address): Moved here.
|
||
Provided warnings for TLS `errno' on non-TLS targets.
|
||
* target.h (target_translate_tls_address): Moved here.
|
||
* eval.c (evaluate_subexp_standard): New `UNOP_MEMVAL_TLS'.
|
||
* expprint.c (print_subexp_standard): New `UNOP_MEMVAL_TLS'.
|
||
(op_name_standard): New `UNOP_MEMVAL_TLS'.
|
||
(dump_subexp_body_standard): New `UNOP_MEMVAL_TLS'.
|
||
* expression.h (enum exp_opcode): New `UNOP_MEMVAL_TLS'.
|
||
(union exp_element): New `objfile' type.
|
||
* parse.c (write_exp_elt_objfile): New `objfile' setter.
|
||
(write_exp_msymbol): Support new `UNOP_MEMVAL_TLS'.
|
||
(msym_text_tls_symbol_type, msym_data_tls_symbol_type,
|
||
msym_unknown_tls_symbol_type, build_parse): New TLS types.
|
||
(operator_length_standard): New `UNOP_MEMVAL_TLS'.
|
||
* parser-defs.h (write_exp_elt_objfile): New `objfile' setter.
|
||
* valops.c (value_at_lazy): Pass control to `value_at_lazy_tls'.
|
||
(value_at_lazy_tls): Provide TLS `struct objfile *' storage.
|
||
(value_fetch_lazy): Resolve TLS `struct objfile *' storage.
|
||
(value_assign): Resolve TLS `struct objfile *' storage.
|
||
* value.c (struct value, allocate_value, value_tls_objfile,
|
||
set_value_tls_objfile): Provide TLS `struct objfile *' storage.
|
||
* value.h (value_tls_objfile, set_value_tls_objfile,
|
||
value_at_lazy_tls): Provide TLS `struct objfile *' storage.
|
||
* Makefile.in: Updated dependencies.
|
||
|
||
2006-08-25 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||
|
||
* gdb.threads/tls-nodebug.c: New file, test TLS symbols on gcc -s.
|
||
* gdb.threads/tls-nodebug.exp: New file, test TLS symbols on gcc -s.
|
||
|
||
|
||
Index: gdb-6.5/gdb/Makefile.in
|
||
===================================================================
|
||
RCS file: /cvs/src/src/gdb/Makefile.in,v
|
||
retrieving revision 1.840
|
||
diff -u -p -r1.840 gdb-6.5/gdb/Makefile.in
|
||
--- gdb-6.5.org/gdb/Makefile.in 22 Aug 2006 19:08:31 -0000 1.840
|
||
+++ gdb-6.5/gdb/Makefile.in 25 Aug 2006 19:55:35 -0000
|
||
@@ -1977,7 +1977,7 @@ exec.o: exec.c $(defs_h) $(frame_h) $(in
|
||
$(xcoffsolib_h) $(observer_h)
|
||
expprint.o: expprint.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \
|
||
$(value_h) $(language_h) $(parser_defs_h) $(user_regs_h) $(target_h) \
|
||
- $(gdb_string_h) $(block_h)
|
||
+ $(gdb_string_h) $(block_h) $(objfiles_h)
|
||
fbsd-nat.o: fbsd-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) $(regcache_h) \
|
||
$(regset_h) $(gdb_assert_h) $(gdb_string_h) $(elf_bfd_h) \
|
||
$(fbsd_nat_h)
|
||
@@ -2422,7 +2422,7 @@ osabi.o: osabi.c $(defs_h) $(gdb_assert_
|
||
parse.o: parse.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
|
||
$(frame_h) $(expression_h) $(value_h) $(command_h) $(language_h) \
|
||
$(f_lang_h) $(parser_defs_h) $(gdbcmd_h) $(symfile_h) $(inferior_h) \
|
||
- $(doublest_h) $(gdb_assert_h) $(block_h) $(source_h)
|
||
+ $(doublest_h) $(gdb_assert_h) $(block_h) $(source_h) $(objfiles_h)
|
||
p-exp.o: p-exp.c $(defs_h) $(gdb_string_h) $(expression_h) $(value_h) \
|
||
$(parser_defs_h) $(language_h) $(p_lang_h) $(bfd_h) $(symfile_h) \
|
||
$(objfiles_h) $(block_h)
|
||
@@ -2750,7 +2750,8 @@ symtab.o: symtab.c $(defs_h) $(symtab_h)
|
||
$(gdb_stat_h) $(cp_abi_h) $(observer_h)
|
||
target.o: target.c $(defs_h) $(gdb_string_h) $(target_h) $(gdbcmd_h) \
|
||
$(symtab_h) $(inferior_h) $(bfd_h) $(symfile_h) $(objfiles_h) \
|
||
- $(gdb_wait_h) $(dcache_h) $(regcache_h) $(gdb_assert_h) $(gdbcore_h)
|
||
+ $(gdb_wait_h) $(dcache_h) $(regcache_h) $(gdb_assert_h) $(gdbcore_h) \
|
||
+ $(exceptions_h)
|
||
thread.o: thread.c $(defs_h) $(symtab_h) $(frame_h) $(inferior_h) \
|
||
$(environ_h) $(value_h) $(target_h) $(gdbthread_h) $(exceptions_h) \
|
||
$(command_h) $(gdbcmd_h) $(regcache_h) $(gdb_h) $(gdb_string_h) \
|
||
Index: gdb-6.5/gdb/dwarf2loc.c
|
||
===================================================================
|
||
RCS file: /cvs/src/src/gdb/dwarf2loc.c,v
|
||
retrieving revision 1.33
|
||
diff -u -p -r1.33 gdb-6.5/gdb/dwarf2loc.c
|
||
--- gdb-6.5.org/gdb/dwarf2loc.c 17 Dec 2005 22:33:59 -0000 1.33
|
||
+++ gdb-6.5/gdb/dwarf2loc.c 25 Aug 2006 19:55:36 -0000
|
||
@@ -189,86 +189,8 @@ static CORE_ADDR
|
||
dwarf_expr_tls_address (void *baton, CORE_ADDR offset)
|
||
{
|
||
struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
|
||
- volatile CORE_ADDR addr = 0;
|
||
|
||
- if (target_get_thread_local_address_p ()
|
||
- && gdbarch_fetch_tls_load_module_address_p (current_gdbarch))
|
||
- {
|
||
- ptid_t ptid = inferior_ptid;
|
||
- struct objfile *objfile = debaton->objfile;
|
||
- volatile struct gdb_exception ex;
|
||
-
|
||
- TRY_CATCH (ex, RETURN_MASK_ALL)
|
||
- {
|
||
- CORE_ADDR lm_addr;
|
||
-
|
||
- /* Fetch the load module address for this objfile. */
|
||
- lm_addr = gdbarch_fetch_tls_load_module_address (current_gdbarch,
|
||
- objfile);
|
||
- /* If it's 0, throw the appropriate exception. */
|
||
- if (lm_addr == 0)
|
||
- throw_error (TLS_LOAD_MODULE_NOT_FOUND_ERROR,
|
||
- _("TLS load module not found"));
|
||
-
|
||
- addr = target_get_thread_local_address (ptid, lm_addr, offset);
|
||
- }
|
||
- /* If an error occurred, print TLS related messages here. Otherwise,
|
||
- throw the error to some higher catcher. */
|
||
- if (ex.reason < 0)
|
||
- {
|
||
- int objfile_is_library = (objfile->flags & OBJF_SHARED);
|
||
-
|
||
- switch (ex.error)
|
||
- {
|
||
- case TLS_NO_LIBRARY_SUPPORT_ERROR:
|
||
- error (_("Cannot find thread-local variables in this thread library."));
|
||
- break;
|
||
- case TLS_LOAD_MODULE_NOT_FOUND_ERROR:
|
||
- if (objfile_is_library)
|
||
- error (_("Cannot find shared library `%s' in dynamic"
|
||
- " linker's load module list"), objfile->name);
|
||
- else
|
||
- error (_("Cannot find executable file `%s' in dynamic"
|
||
- " linker's load module list"), objfile->name);
|
||
- break;
|
||
- case TLS_NOT_ALLOCATED_YET_ERROR:
|
||
- if (objfile_is_library)
|
||
- error (_("The inferior has not yet allocated storage for"
|
||
- " thread-local variables in\n"
|
||
- "the shared library `%s'\n"
|
||
- "for %s"),
|
||
- objfile->name, target_pid_to_str (ptid));
|
||
- else
|
||
- error (_("The inferior has not yet allocated storage for"
|
||
- " thread-local variables in\n"
|
||
- "the executable `%s'\n"
|
||
- "for %s"),
|
||
- objfile->name, target_pid_to_str (ptid));
|
||
- break;
|
||
- case TLS_GENERIC_ERROR:
|
||
- if (objfile_is_library)
|
||
- error (_("Cannot find thread-local storage for %s, "
|
||
- "shared library %s:\n%s"),
|
||
- target_pid_to_str (ptid),
|
||
- objfile->name, ex.message);
|
||
- else
|
||
- error (_("Cannot find thread-local storage for %s, "
|
||
- "executable file %s:\n%s"),
|
||
- target_pid_to_str (ptid),
|
||
- objfile->name, ex.message);
|
||
- break;
|
||
- default:
|
||
- throw_exception (ex);
|
||
- break;
|
||
- }
|
||
- }
|
||
- }
|
||
- /* It wouldn't be wrong here to try a gdbarch method, too; finding
|
||
- TLS is an ABI-specific thing. But we don't do that yet. */
|
||
- else
|
||
- error (_("Cannot find thread-local variables on this target"));
|
||
-
|
||
- return addr;
|
||
+ return target_translate_tls_address (debaton->objfile, offset);
|
||
}
|
||
|
||
/* Evaluate a location description, starting at DATA and with length
|
||
Index: gdb-6.5/gdb/eval.c
|
||
===================================================================
|
||
RCS file: /cvs/src/src/gdb/eval.c,v
|
||
retrieving revision 1.63
|
||
diff -u -p -r1.63 gdb-6.5/gdb/eval.c
|
||
--- gdb-6.5.org/gdb/eval.c 25 Jul 2006 04:24:50 -0000 1.63
|
||
+++ gdb-6.5/gdb/eval.c 25 Aug 2006 19:55:38 -0000
|
||
@@ -2019,6 +2019,18 @@ evaluate_subexp_standard (struct type *e
|
||
return value_at_lazy (exp->elts[pc + 1].type,
|
||
value_as_address (arg1));
|
||
|
||
+ case UNOP_MEMVAL_TLS:
|
||
+ (*pos) += 3;
|
||
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
|
||
+ if (noside == EVAL_SKIP)
|
||
+ goto nosideret;
|
||
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
|
||
+ return value_zero (exp->elts[pc + 2].type, lval_memory);
|
||
+ else
|
||
+ return value_at_lazy_tls (exp->elts[pc + 2].type,
|
||
+ value_as_address (arg1),
|
||
+ exp->elts[pc + 1].objfile);
|
||
+
|
||
case UNOP_PREINCREMENT:
|
||
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
|
||
if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
|
||
Index: gdb-6.5/gdb/expprint.c
|
||
===================================================================
|
||
RCS file: /cvs/src/src/gdb/expprint.c,v
|
||
retrieving revision 1.24
|
||
diff -u -p -r1.24 gdb-6.5/gdb/expprint.c
|
||
--- gdb-6.5.org/gdb/expprint.c 7 Aug 2006 03:30:54 -0000 1.24
|
||
+++ gdb-6.5/gdb/expprint.c 25 Aug 2006 19:55:39 -0000
|
||
@@ -31,6 +31,7 @@
|
||
#include "target.h"
|
||
#include "gdb_string.h"
|
||
#include "block.h"
|
||
+#include "objfiles.h"
|
||
|
||
#ifdef HAVE_CTYPE_H
|
||
#include <ctype.h>
|
||
@@ -414,6 +415,33 @@ print_subexp_standard (struct expression
|
||
fputs_filtered (")", stream);
|
||
return;
|
||
|
||
+ case UNOP_MEMVAL_TLS:
|
||
+ (*pos) += 3;
|
||
+ if ((int) prec > (int) PREC_PREFIX)
|
||
+ fputs_filtered ("(", stream);
|
||
+ if (TYPE_CODE (exp->elts[pc + 2].type) == TYPE_CODE_FUNC &&
|
||
+ exp->elts[pc + 4].opcode == OP_LONG)
|
||
+ {
|
||
+ /* We have a minimal symbol fn, probably. It's encoded
|
||
+ as a UNOP_MEMVAL (function-type) of an OP_LONG (int, address).
|
||
+ Swallow the OP_LONG (including both its opcodes); ignore
|
||
+ its type; print the value in the type of the MEMVAL. */
|
||
+ (*pos) += 4;
|
||
+ val = value_at_lazy (exp->elts[pc + 2].type,
|
||
+ (CORE_ADDR) exp->elts[pc + 6].longconst);
|
||
+ value_print (val, stream, 0, Val_no_prettyprint);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ fputs_filtered ("{", stream);
|
||
+ type_print (exp->elts[pc + 2].type, "", stream, 0);
|
||
+ fputs_filtered ("} ", stream);
|
||
+ print_subexp (exp, pos, stream, PREC_PREFIX);
|
||
+ }
|
||
+ if ((int) prec > (int) PREC_PREFIX)
|
||
+ fputs_filtered (")", stream);
|
||
+ return;
|
||
+
|
||
case BINOP_ASSIGN_MODIFY:
|
||
opcode = exp->elts[pc + 1].opcode;
|
||
(*pos) += 2;
|
||
@@ -694,6 +722,8 @@ op_name_standard (enum exp_opcode opcode
|
||
return "UNOP_CAST";
|
||
case UNOP_MEMVAL:
|
||
return "UNOP_MEMVAL";
|
||
+ case UNOP_MEMVAL_TLS:
|
||
+ return "UNOP_MEMVAL_TLS";
|
||
case UNOP_NEG:
|
||
return "UNOP_NEG";
|
||
case UNOP_LOGICAL_NOT:
|
||
@@ -999,6 +1029,16 @@ dump_subexp_body_standard (struct expres
|
||
fprintf_filtered (stream, ")");
|
||
elt = dump_subexp (exp, stream, elt + 2);
|
||
break;
|
||
+ case UNOP_MEMVAL_TLS:
|
||
+ fprintf_filtered (stream, "TLS type @");
|
||
+ gdb_print_host_address (exp->elts[elt + 1].type, stream);
|
||
+ fprintf_filtered (stream, " (__thread /* \"%s\" */ ",
|
||
+ (exp->elts[elt].objfile == NULL ? "(null)"
|
||
+ : exp->elts[elt].objfile->name));
|
||
+ type_print (exp->elts[elt + 1].type, NULL, stream, 0);
|
||
+ fprintf_filtered (stream, ")");
|
||
+ elt = dump_subexp (exp, stream, elt + 3);
|
||
+ break;
|
||
case OP_TYPE:
|
||
fprintf_filtered (stream, "Type @");
|
||
gdb_print_host_address (exp->elts[elt].type, stream);
|
||
Index: gdb-6.5/gdb/expression.h
|
||
===================================================================
|
||
RCS file: /cvs/src/src/gdb/expression.h,v
|
||
retrieving revision 1.18
|
||
diff -u -p -r1.18 gdb-6.5/gdb/expression.h
|
||
--- gdb-6.5.org/gdb/expression.h 17 Dec 2005 22:33:59 -0000 1.18
|
||
+++ gdb-6.5/gdb/expression.h 25 Aug 2006 19:55:40 -0000
|
||
@@ -234,6 +234,13 @@ enum exp_opcode
|
||
following subexpression. */
|
||
UNOP_MEMVAL,
|
||
|
||
+ /* UNOP_MEMVAL_TLS is followed by a `struct objfile' pointer in the next
|
||
+ exp_element and a type pointer in the following exp_element.
|
||
+ With another UNOP_MEMVAL_TLS at the end, this makes four exp_elements.
|
||
+ It casts the contents of the word offsetted by the value of the
|
||
+ following subexpression from the TLS specified by `struct objfile'. */
|
||
+ UNOP_MEMVAL_TLS,
|
||
+
|
||
/* UNOP_... operate on one value from a following subexpression
|
||
and replace it with a result. They take no immediate arguments. */
|
||
|
||
@@ -360,6 +367,7 @@ union exp_element
|
||
struct type *type;
|
||
struct internalvar *internalvar;
|
||
struct block *block;
|
||
+ struct objfile *objfile;
|
||
};
|
||
|
||
struct expression
|
||
Index: gdb-6.5/gdb/parse.c
|
||
===================================================================
|
||
RCS file: /cvs/src/src/gdb/parse.c,v
|
||
retrieving revision 1.53
|
||
diff -u -p -r1.53 gdb-6.5/gdb/parse.c
|
||
--- gdb-6.5.org/gdb/parse.c 6 Jul 2006 14:00:48 -0000 1.53
|
||
+++ gdb-6.5/gdb/parse.c 25 Aug 2006 19:55:41 -0000
|
||
@@ -53,6 +53,7 @@
|
||
#include "gdb_assert.h"
|
||
#include "block.h"
|
||
#include "source.h"
|
||
+#include "objfiles.h"
|
||
|
||
/* Standard set of definitions for printing, dumping, prefixifying,
|
||
* and evaluating expressions. */
|
||
@@ -219,6 +220,15 @@ write_exp_elt_block (struct block *b)
|
||
}
|
||
|
||
void
|
||
+write_exp_elt_objfile (struct objfile *objfile)
|
||
+{
|
||
+ union exp_element tmp;
|
||
+ memset (&tmp, 0, sizeof (union exp_element));
|
||
+ tmp.objfile = objfile;
|
||
+ write_exp_elt (tmp);
|
||
+}
|
||
+
|
||
+void
|
||
write_exp_elt_longcst (LONGEST expelt)
|
||
{
|
||
union exp_element tmp;
|
||
@@ -378,6 +388,9 @@ write_exp_bitstring (struct stoken str)
|
||
static struct type *msym_text_symbol_type;
|
||
static struct type *msym_data_symbol_type;
|
||
static struct type *msym_unknown_symbol_type;
|
||
+static struct type *msym_text_tls_symbol_type;
|
||
+static struct type *msym_data_tls_symbol_type;
|
||
+static struct type *msym_unknown_tls_symbol_type;
|
||
|
||
void
|
||
write_exp_msymbol (struct minimal_symbol *msymbol,
|
||
@@ -385,6 +398,8 @@ write_exp_msymbol (struct minimal_symbol
|
||
struct type *data_symbol_type)
|
||
{
|
||
CORE_ADDR addr;
|
||
+ int tls = SYMBOL_BFD_SECTION (msymbol)->flags & SEC_THREAD_LOCAL;
|
||
+ enum exp_opcode opcode = tls ? UNOP_MEMVAL_TLS : UNOP_MEMVAL;
|
||
|
||
write_exp_elt_opcode (OP_LONG);
|
||
/* Let's make the type big enough to hold a 64-bit address. */
|
||
@@ -397,27 +412,49 @@ write_exp_msymbol (struct minimal_symbol
|
||
|
||
write_exp_elt_opcode (OP_LONG);
|
||
|
||
- write_exp_elt_opcode (UNOP_MEMVAL);
|
||
+ write_exp_elt_opcode (opcode);
|
||
+
|
||
+ if (opcode == UNOP_MEMVAL_TLS)
|
||
+ {
|
||
+ bfd *bfd = SYMBOL_BFD_SECTION (msymbol)->owner;
|
||
+ struct objfile *ofp;
|
||
+
|
||
+ ALL_OBJFILES (ofp)
|
||
+ if (ofp->obfd == bfd)
|
||
+ break;
|
||
+ write_exp_elt_objfile (ofp);
|
||
+ }
|
||
+
|
||
switch (msymbol->type)
|
||
{
|
||
case mst_text:
|
||
case mst_file_text:
|
||
case mst_solib_trampoline:
|
||
- write_exp_elt_type (msym_text_symbol_type);
|
||
+ if (tls)
|
||
+ write_exp_elt_type (msym_text_tls_symbol_type);
|
||
+ else
|
||
+ write_exp_elt_type (msym_text_symbol_type);
|
||
break;
|
||
|
||
case mst_data:
|
||
case mst_file_data:
|
||
case mst_bss:
|
||
case mst_file_bss:
|
||
- write_exp_elt_type (msym_data_symbol_type);
|
||
+ if (tls)
|
||
+ write_exp_elt_type (msym_data_tls_symbol_type);
|
||
+ else
|
||
+ write_exp_elt_type (msym_data_symbol_type);
|
||
break;
|
||
|
||
default:
|
||
- write_exp_elt_type (msym_unknown_symbol_type);
|
||
+ if (tls)
|
||
+ write_exp_elt_type (msym_unknown_tls_symbol_type);
|
||
+ else
|
||
+ write_exp_elt_type (msym_unknown_symbol_type);
|
||
break;
|
||
}
|
||
- write_exp_elt_opcode (UNOP_MEMVAL);
|
||
+
|
||
+ write_exp_elt_opcode (opcode);
|
||
}
|
||
|
||
/* Recognize tokens that start with '$'. These include:
|
||
@@ -904,6 +941,11 @@ operator_length_standard (struct express
|
||
args = 1;
|
||
break;
|
||
|
||
+ case UNOP_MEMVAL_TLS:
|
||
+ oplen = 4;
|
||
+ args = 1;
|
||
+ break;
|
||
+
|
||
case UNOP_ABS:
|
||
case UNOP_CAP:
|
||
case UNOP_CHR:
|
||
@@ -1341,6 +1383,17 @@ build_parse (void)
|
||
init_type (TYPE_CODE_INT, 1, 0,
|
||
"<variable (not text or data), no debug info>",
|
||
NULL);
|
||
+
|
||
+ msym_text_tls_symbol_type =
|
||
+ init_type (TYPE_CODE_FUNC, 1, 0, "<TLS-based text variable, no debug info>", NULL);
|
||
+ TYPE_TARGET_TYPE (msym_text_tls_symbol_type) = builtin_type_int;
|
||
+ msym_data_tls_symbol_type =
|
||
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / HOST_CHAR_BIT, 0,
|
||
+ "<TLS-based data variable, no debug info>", NULL);
|
||
+ msym_unknown_tls_symbol_type =
|
||
+ init_type (TYPE_CODE_INT, 1, 0,
|
||
+ "<TLS-based variable (not text or data), no debug info>",
|
||
+ NULL);
|
||
}
|
||
|
||
/* This function avoids direct calls to fprintf
|
||
Index: gdb-6.5/gdb/parser-defs.h
|
||
===================================================================
|
||
RCS file: /cvs/src/src/gdb/parser-defs.h,v
|
||
retrieving revision 1.20
|
||
diff -u -p -r1.20 gdb-6.5/gdb/parser-defs.h
|
||
--- gdb-6.5.org/gdb/parser-defs.h 17 Dec 2005 22:34:01 -0000 1.20
|
||
+++ gdb-6.5/gdb/parser-defs.h 25 Aug 2006 19:55:41 -0000
|
||
@@ -131,6 +131,8 @@ extern void write_exp_bitstring (struct
|
||
|
||
extern void write_exp_elt_block (struct block *);
|
||
|
||
+extern void write_exp_elt_objfile (struct objfile *objfile);
|
||
+
|
||
extern void write_exp_msymbol (struct minimal_symbol *,
|
||
struct type *, struct type *);
|
||
|
||
--- gdb-6.5.org/gdb/target.c 16 Aug 2006 18:31:03 -0000 1.124
|
||
+++ gdb-6.5/gdb/target.c 25 Aug 2006 19:55:43 -0000
|
||
@@ -40,6 +40,7 @@
|
||
#include "gdb_assert.h"
|
||
#include "gdbcore.h"
|
||
#include "observer.h"
|
||
+#include "exceptions.h"
|
||
|
||
static void target_info (char *, int);
|
||
|
||
@@ -755,6 +756,103 @@ pop_target (void)
|
||
internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
|
||
}
|
||
|
||
+/* Using the objfile specified in BATON, find the address for the
|
||
+ current thread's thread-local storage with offset OFFSET. */
|
||
+CORE_ADDR
|
||
+target_translate_tls_address (struct objfile *objfile, CORE_ADDR offset)
|
||
+{
|
||
+ volatile CORE_ADDR addr = 0;
|
||
+
|
||
+ if (target_get_thread_local_address_p ()
|
||
+ && gdbarch_fetch_tls_load_module_address_p (current_gdbarch))
|
||
+ {
|
||
+ ptid_t ptid = inferior_ptid;
|
||
+ volatile struct gdb_exception ex;
|
||
+
|
||
+ TRY_CATCH (ex, RETURN_MASK_ALL)
|
||
+ {
|
||
+ CORE_ADDR lm_addr;
|
||
+
|
||
+ /* Fetch the load module address for this objfile. */
|
||
+ lm_addr = gdbarch_fetch_tls_load_module_address (current_gdbarch,
|
||
+ objfile);
|
||
+ /* If it's 0, throw the appropriate exception. */
|
||
+ if (lm_addr == 0)
|
||
+ throw_error (TLS_LOAD_MODULE_NOT_FOUND_ERROR,
|
||
+ _("TLS load module not found"));
|
||
+
|
||
+ addr = target_get_thread_local_address (ptid, lm_addr, offset);
|
||
+ }
|
||
+ /* If an error occurred, print TLS related messages here. Otherwise,
|
||
+ throw the error to some higher catcher. */
|
||
+ if (ex.reason < 0)
|
||
+ {
|
||
+ int objfile_is_library = (objfile->flags & OBJF_SHARED);
|
||
+
|
||
+ switch (ex.error)
|
||
+ {
|
||
+ case TLS_NO_LIBRARY_SUPPORT_ERROR:
|
||
+ error (_("Cannot find thread-local variables in this thread library."));
|
||
+ break;
|
||
+ case TLS_LOAD_MODULE_NOT_FOUND_ERROR:
|
||
+ if (objfile_is_library)
|
||
+ error (_("Cannot find shared library `%s' in dynamic"
|
||
+ " linker's load module list"), objfile->name);
|
||
+ else
|
||
+ error (_("Cannot find executable file `%s' in dynamic"
|
||
+ " linker's load module list"), objfile->name);
|
||
+ break;
|
||
+ case TLS_NOT_ALLOCATED_YET_ERROR:
|
||
+ if (objfile_is_library)
|
||
+ error (_("The inferior has not yet allocated storage for"
|
||
+ " thread-local variables in\n"
|
||
+ "the shared library `%s'\n"
|
||
+ "for %s"),
|
||
+ objfile->name, target_pid_to_str (ptid));
|
||
+ else
|
||
+ error (_("The inferior has not yet allocated storage for"
|
||
+ " thread-local variables in\n"
|
||
+ "the executable `%s'\n"
|
||
+ "for %s"),
|
||
+ objfile->name, target_pid_to_str (ptid));
|
||
+ break;
|
||
+ case TLS_GENERIC_ERROR:
|
||
+ if (objfile_is_library)
|
||
+ error (_("Cannot find thread-local storage for %s, "
|
||
+ "shared library %s:\n%s"),
|
||
+ target_pid_to_str (ptid),
|
||
+ objfile->name, ex.message);
|
||
+ else
|
||
+ error (_("Cannot find thread-local storage for %s, "
|
||
+ "executable file %s:\n%s"),
|
||
+ target_pid_to_str (ptid),
|
||
+ objfile->name, ex.message);
|
||
+ break;
|
||
+ default:
|
||
+ throw_exception (ex);
|
||
+ break;
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ /* It wouldn't be wrong here to try a gdbarch method, too; finding
|
||
+ TLS is an ABI-specific thing. But we don't do that yet. */
|
||
+ else
|
||
+ {
|
||
+ struct minimal_symbol *msymbol;
|
||
+
|
||
+ msymbol = lookup_minimal_symbol ("errno", NULL, NULL);
|
||
+ if (msymbol != NULL
|
||
+ && SYMBOL_VALUE_ADDRESS (msymbol) == offset
|
||
+ && SYMBOL_BFD_SECTION (msymbol)->owner == objfile->obfd)
|
||
+ error (_("TLS symbol `errno' not resolved for non-TLS program."
|
||
+ " You should use symbol \"(*__errno_location ())\" or"
|
||
+ " compile the program with `gcc -ggdb3' or `gcc -pthread'."));
|
||
+ error (_("Cannot find thread-local variables on this target"));
|
||
+ }
|
||
+
|
||
+ return addr;
|
||
+}
|
||
+
|
||
#undef MIN
|
||
#define MIN(A, B) (((A) <= (B)) ? (A) : (B))
|
||
|
||
Index: gdb-6.5/gdb/target.h
|
||
===================================================================
|
||
RCS file: /cvs/src/src/gdb/target.h,v
|
||
retrieving revision 1.87
|
||
diff -u -p -r1.87 gdb-6.5/gdb/target.h
|
||
--- gdb-6.5.org/gdb/target.h 15 Aug 2006 18:46:25 -0000 1.87
|
||
+++ gdb-6.5/gdb/target.h 25 Aug 2006 19:55:44 -0000
|
||
@@ -1131,6 +1131,9 @@ extern void target_preopen (int);
|
||
|
||
extern void pop_target (void);
|
||
|
||
+extern CORE_ADDR target_translate_tls_address (struct objfile *objfile,
|
||
+ CORE_ADDR offset);
|
||
+
|
||
/* Struct section_table maps address ranges to file sections. It is
|
||
mostly used with BFD files, but can be used without (e.g. for handling
|
||
raw disks, or files not in formats handled by BFD). */
|
||
Index: gdb-6.5/gdb/valops.c
|
||
===================================================================
|
||
RCS file: /cvs/src/src/gdb/valops.c,v
|
||
retrieving revision 1.164
|
||
diff -u -p -r1.164 gdb-6.5/gdb/valops.c
|
||
--- gdb-6.5.org/gdb/valops.c 13 Jul 2006 04:31:42 -0000 1.164
|
||
+++ gdb-6.5/gdb/valops.c 25 Aug 2006 19:55:46 -0000
|
||
@@ -501,7 +501,8 @@ value_at (struct type *type, CORE_ADDR a
|
||
/* Return a lazy value with type TYPE located at ADDR (cf. value_at). */
|
||
|
||
struct value *
|
||
-value_at_lazy (struct type *type, CORE_ADDR addr)
|
||
+value_at_lazy_tls (struct type *type, CORE_ADDR addr,
|
||
+ struct objfile *tls_objfile)
|
||
{
|
||
struct value *val;
|
||
|
||
@@ -512,11 +513,19 @@ value_at_lazy (struct type *type, CORE_A
|
||
|
||
VALUE_LVAL (val) = lval_memory;
|
||
VALUE_ADDRESS (val) = addr;
|
||
+ if (tls_objfile != NULL)
|
||
+ set_value_tls_objfile (val, tls_objfile);
|
||
set_value_lazy (val, 1);
|
||
|
||
return val;
|
||
}
|
||
|
||
+struct value *
|
||
+value_at_lazy (struct type *type, CORE_ADDR addr)
|
||
+{
|
||
+ return value_at_lazy_tls (type, addr, NULL);
|
||
+}
|
||
+
|
||
/* Called only from the value_contents and value_contents_all()
|
||
macros, if the current data for a variable needs to be loaded into
|
||
value_contents(VAL). Fetches the data from the user's process, and
|
||
@@ -538,7 +547,17 @@ value_fetch_lazy (struct value *val)
|
||
|
||
struct type *type = value_type (val);
|
||
if (length)
|
||
- read_memory (addr, value_contents_all_raw (val), length);
|
||
+ {
|
||
+ struct objfile *tls_objfile = value_tls_objfile (val);
|
||
+
|
||
+ if (tls_objfile != NULL)
|
||
+ {
|
||
+ /* `target_translate_tls_address' uses `inferior_ptid'. */
|
||
+ addr = target_translate_tls_address (tls_objfile, addr);
|
||
+ }
|
||
+
|
||
+ read_memory (addr, value_contents_all_raw (val), length);
|
||
+ }
|
||
|
||
set_value_lazy (val, 0);
|
||
return 0;
|
||
@@ -596,6 +615,7 @@ value_assign (struct value *toval, struc
|
||
CORE_ADDR changed_addr;
|
||
int changed_len;
|
||
gdb_byte buffer[sizeof (LONGEST)];
|
||
+ struct objfile *tls_objfile = value_tls_objfile (toval);
|
||
|
||
if (value_bitsize (toval))
|
||
{
|
||
@@ -624,6 +644,13 @@ value_assign (struct value *toval, struc
|
||
dest_buffer = value_contents (fromval);
|
||
}
|
||
|
||
+ if (tls_objfile != NULL)
|
||
+ {
|
||
+ /* `target_translate_tls_address' uses `inferior_ptid'. */
|
||
+ changed_addr = target_translate_tls_address (tls_objfile,
|
||
+ changed_addr);
|
||
+ }
|
||
+
|
||
write_memory (changed_addr, dest_buffer, changed_len);
|
||
if (deprecated_memory_changed_hook)
|
||
deprecated_memory_changed_hook (changed_addr, changed_len);
|
||
Index: gdb-6.5/gdb/value.c
|
||
===================================================================
|
||
RCS file: /cvs/src/src/gdb/value.c,v
|
||
retrieving revision 1.36
|
||
diff -u -p -r1.36 gdb-6.5/gdb/value.c
|
||
--- gdb-6.5.org/gdb/value.c 31 Mar 2006 10:36:18 -0000 1.36
|
||
+++ gdb-6.5/gdb/value.c 25 Aug 2006 19:55:47 -0000
|
||
@@ -158,6 +158,9 @@ struct value
|
||
actually exist in the program. */
|
||
char optimized_out;
|
||
|
||
+ /* TLS owner. */
|
||
+ struct objfile *tls_objfile;
|
||
+
|
||
/* Actual contents of the value. For use of this value; setting it
|
||
uses the stuff above. Not valid if lazy is nonzero. Target
|
||
byte-order. We force it to be aligned properly for any possible
|
||
@@ -230,6 +233,7 @@ allocate_value (struct type *type)
|
||
VALUE_REGNUM (val) = -1;
|
||
val->lazy = 0;
|
||
val->optimized_out = 0;
|
||
+ val->tls_objfile = NULL;
|
||
val->embedded_offset = 0;
|
||
val->pointed_to_offset = 0;
|
||
val->modifiable = 1;
|
||
@@ -344,6 +348,18 @@ set_value_lazy (struct value *value, int
|
||
value->lazy = val;
|
||
}
|
||
|
||
+struct objfile *
|
||
+value_tls_objfile (struct value *value)
|
||
+{
|
||
+ return value->tls_objfile;
|
||
+}
|
||
+
|
||
+void
|
||
+set_value_tls_objfile (struct value *value, struct objfile *tls_objfile)
|
||
+{
|
||
+ value->tls_objfile = tls_objfile;
|
||
+}
|
||
+
|
||
const gdb_byte *
|
||
value_contents (struct value *value)
|
||
{
|
||
Index: gdb-6.5/gdb/value.h
|
||
===================================================================
|
||
RCS file: /cvs/src/src/gdb/value.h,v
|
||
retrieving revision 1.92
|
||
diff -u -p -r1.92 gdb-6.5/gdb/value.h
|
||
--- gdb-6.5.org/gdb/value.h 13 Jul 2006 04:31:42 -0000 1.92
|
||
+++ gdb-6.5/gdb/value.h 25 Aug 2006 19:55:48 -0000
|
||
@@ -154,6 +154,10 @@ extern void set_value_embedded_offset (s
|
||
extern int value_lazy (struct value *);
|
||
extern void set_value_lazy (struct value *value, int val);
|
||
|
||
+extern struct objfile *value_tls_objfile (struct value *value);
|
||
+extern void set_value_tls_objfile (struct value *value,
|
||
+ struct objfile *tls_objfile);
|
||
+
|
||
/* value_contents() and value_contents_raw() both return the address
|
||
of the gdb buffer used to hold a copy of the contents of the lval.
|
||
value_contents() is used when the contents of the buffer are needed
|
||
@@ -277,6 +281,8 @@ extern struct value *value_from_double (
|
||
extern struct value *value_from_string (char *string);
|
||
|
||
extern struct value *value_at (struct type *type, CORE_ADDR addr);
|
||
+extern struct value *value_at_lazy_tls (struct type *type, CORE_ADDR addr,
|
||
+ struct objfile *tls_objfile);
|
||
extern struct value *value_at_lazy (struct type *type, CORE_ADDR addr);
|
||
|
||
extern struct value *value_from_register (struct type *type, int regnum,
|
||
Index: gdb-6.5/gdb/testsuite/gdb.threads/tls-nodebug.c
|
||
===================================================================
|
||
RCS file: gdb-6.5/gdb/testsuite/gdb.threads/tls-nodebug.c
|
||
diff -N gdb-6.5/gdb/testsuite/gdb.threads/tls-nodebug.c
|
||
--- /dev/null 1 Jan 1970 00:00:00 -0000
|
||
+++ gdb-6.5/gdb/testsuite/gdb.threads/tls-nodebug.c 25 Aug 2006 19:55:48 -0000
|
||
@@ -0,0 +1,8 @@
|
||
+/* Test accessing TLS based variable without any debug info compiled. */
|
||
+
|
||
+__thread int thread_local = 42;
|
||
+
|
||
+int main(void)
|
||
+{
|
||
+ return 0;
|
||
+}
|
||
Index: gdb-6.5/gdb/testsuite/gdb.threads/tls-nodebug.exp
|
||
===================================================================
|
||
RCS file: gdb-6.5/gdb/testsuite/gdb.threads/tls-nodebug.exp
|
||
diff -N gdb-6.5/gdb/testsuite/gdb.threads/tls-nodebug.exp
|
||
--- /dev/null 1 Jan 1970 00:00:00 -0000
|
||
+++ gdb-6.5/gdb/testsuite/gdb.threads/tls-nodebug.exp 25 Aug 2006 19:55:49 -0000
|
||
@@ -0,0 +1,52 @@
|
||
+# tls.exp -- Expect script to test thread-local storage without debuginfo
|
||
+# Copyright (C) 2006 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 2 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, write to the Free Software
|
||
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||
+
|
||
+# Please email any bugs, comments, and/or additions to this file to:
|
||
+# bug-gdb@prep.ai.mit.edu
|
||
+
|
||
+set testfile tls-nodebug
|
||
+set srcfile ${testfile}.c
|
||
+set binfile ${objdir}/${subdir}/${testfile}
|
||
+
|
||
+if [istarget "*-*-linux"] then {
|
||
+ set target_cflags "-D_MIT_POSIX_THREADS"
|
||
+} else {
|
||
+ set target_cflags ""
|
||
+}
|
||
+
|
||
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable $options] != "" } {
|
||
+ return -1
|
||
+}
|
||
+
|
||
+gdb_exit
|
||
+gdb_start
|
||
+gdb_reinitialize_dir $srcdir/$subdir
|
||
+
|
||
+gdb_load ${binfile}
|
||
+if ![runto_main] then {
|
||
+ fail "Can't run to main"
|
||
+ return 0
|
||
+}
|
||
+
|
||
+# Formerly: Cannot access memory at address 0x0
|
||
+gdb_test "p thread_local" "= 42" "thread local storage"
|
||
+
|
||
+# Done!
|
||
+#
|
||
+gdb_exit
|
||
+
|
||
+return 0
|