TLS variables access for -static -lpthread executables
Jan Kratochvil
jan.kratochvil@redhat.com
Wed Mar 26 18:21:00 GMT 2014
Hi,
Reproducer:
gcc -g -o tlsvar tlsvar.c -pthread -static; gdb ./tlsvar -ex 'b 12' -ex r -ex 'info thread' -ex 'p *thread_local_p'
Actual output:
Cannot find executable file `.../tlsvar' in dynamic linker's load module list
Expected output:
$1 = 10 (or 20 or 30)
With -static there is no _r_debug, no link_map, no '.dynamic' section so there
is nothing to pass as 'psaddr_t __map_address' for td_thr_tls_get_addr.
Attached GDB fix that uses td_thr_tlsbase() instead of td_thr_tls_get_addr()
and pass 'modid' as value 1. But I haven't found it documented anywhere.
Is such patch acceptable for upstream GDB or is there some better way with
glibc?
Thanks,
Jan
-------------- next part --------------
#include <pthread.h>
#include <stdio.h>
__thread int *thread_local_p;
void *start_routine(void *arg)
{
int i = (int)(long)arg;
thread_local_p = &i;
printf ("thread_local_p: & == %016lx, . == %016lx, * == %d\n",
(long)&thread_local_p, (long)thread_local_p, *thread_local_p);
return arg;
}
main()
{
pthread_t handle1, handle2, handle3;
pthread_create(&handle1, NULL, &start_routine, (void *)10);
pthread_create(&handle2, NULL, &start_routine, (void *)20);
pthread_create(&handle3, NULL, &start_routine, (void *)30);
start_routine((void *)0);
pthread_join(handle1, NULL);
pthread_join(handle2, NULL);
pthread_join(handle3, NULL);
}
-------------- next part --------------
diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
index ca614a3..092a896 100644
--- a/gdb/linux-thread-db.c
+++ b/gdb/linux-thread-db.c
@@ -196,6 +196,9 @@ struct thread_db_info
td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th,
psaddr_t map_address,
size_t offset, psaddr_t *address);
+ td_err_e (*td_thr_tlsbase_p) (const td_thrhandle_t *th,
+ unsigned long int modid,
+ psaddr_t *base);
};
/* List of known processes using thread_db, and the required
@@ -799,6 +802,7 @@ try_thread_db_load_1 (struct thread_db_info *info)
info->td_ta_event_getmsg_p = dlsym (info->handle, "td_ta_event_getmsg");
info->td_thr_event_enable_p = dlsym (info->handle, "td_thr_event_enable");
info->td_thr_tls_get_addr_p = dlsym (info->handle, "td_thr_tls_get_addr");
+ info->td_thr_tlsbase_p = dlsym (info->handle, "td_thr_tlsbase");
if (thread_db_find_new_threads_silently (inferior_ptid) != 0)
{
@@ -1811,21 +1815,36 @@ thread_db_get_thread_local_address (struct target_ops *ops,
info = get_thread_db_info (ptid_get_pid (ptid));
- /* glibc doesn't provide the needed interface. */
- if (!info->td_thr_tls_get_addr_p)
- throw_error (TLS_NO_LIBRARY_SUPPORT_ERROR,
- _("No TLS library support"));
-
+#if 0
/* Caller should have verified that lm != 0. */
gdb_assert (lm != 0);
-
+#endif
/* Finally, get the address of the variable. */
- /* Note the cast through uintptr_t: this interface only works if
- a target address fits in a psaddr_t, which is a host pointer.
- So a 32-bit debugger can not access 64-bit TLS through this. */
- err = info->td_thr_tls_get_addr_p (&thread_info->private->th,
- (psaddr_t)(uintptr_t) lm,
- offset, &address);
+ if (lm != 0)
+ {
+ /* glibc doesn't provide the needed interface. */
+ if (!info->td_thr_tls_get_addr_p)
+ throw_error (TLS_NO_LIBRARY_SUPPORT_ERROR,
+ _("No TLS library support"));
+
+ /* Note the cast through uintptr_t: this interface only works if
+ a target address fits in a psaddr_t, which is a host pointer.
+ So a 32-bit debugger can not access 64-bit TLS through this. */
+ err = info->td_thr_tls_get_addr_p (&thread_info->private->th,
+ (psaddr_t)(uintptr_t) lm,
+ offset, &address);
+ }
+ else
+ {
+ /* glibc doesn't provide the needed interface. */
+ if (!info->td_thr_tlsbase_p)
+ throw_error (TLS_NO_LIBRARY_SUPPORT_ERROR,
+ _("No TLS library support"));
+
+ err = info->td_thr_tlsbase_p (&thread_info->private->th,
+ 1, &address);
+ address = (char *) address + offset;
+ }
#ifdef THREAD_DB_HAS_TD_NOTALLOC
/* The memory hasn't been allocated, yet. */
diff --git a/gdb/target.c b/gdb/target.c
index 1b48f79..e2cc446 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -753,10 +753,12 @@ target_translate_tls_address (struct objfile *objfile, CORE_ADDR offset)
/* Fetch the load module address for this objfile. */
lm_addr = gdbarch_fetch_tls_load_module_address (target_gdbarch (),
objfile);
+#if 0
/* 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"));
+#endif
addr = target->to_get_thread_local_address (target, ptid,
lm_addr, offset);
More information about the Libc-help
mailing list