This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: NPTL libthread_db changes for static debugging


> I believe so.  Of course they may or may not return TD_ERR; it depends
> what happens when they do their bogus read.

Sure.  Read as: some nonspecific error.

> The bigger problem is that we can not enable event reporting for
> pthread_create until after we know the thread's ID (since NPTL checks
> THREAD_SELF->report_events).  GDB also uses PTRACE_EVENT_CLONE to
> detect clones, so it can recover, but it seems to me that you should
> be able to use libthread_db in this way without having to track
> clones too.
[...]
> It also causes a few problems in the GDB testsuite; it breaks TLS
> support because we decide we're dealing with a non-threaded program.

I think these two problems make the zero-threads interface a nonstarter.

What do you think about the following (wholly untested) patch instead?

This goes back to faking a special-case td_thrhandle_t for the
uninitialized case.  However, it uses 0 for th_unique in the faked handle.
All the calls accept this special-case handle appropriately.  
For td_thr_event_enable that uses a global flag propagated to the initial
thread at initialization time.  td_thr_tlsbase looks up the thread register
and tries it if it's nonzero, because I figure garbage in the worst case is
better than never trying and not being able to resolve TLS.  You only get
garbage when the kernel doesn't clear the register and you try to look at
TLS before it exists.

This makes ti_tid and the behavior of td_ta_map_id2thr match the value of
pthread_self () in the inferior at the time of the interrogation, which is
also zero in e.g. a dynamic program not using libpthread (but that might or
might not later dlopen it)--though I guess you won't get td_ta_new to work
then anyway.  

Unless this is just buggy, the only issue I see is if callers (gdb) don't
like the th_unique and ti_tid values for the LWP changing.  If you don't
retain info from td_thrhandle_t's after resuming from a stop, a fresh
td_ta_thr_iter or td_ta_map_lwp2thr done later after initialization will
have the real pointer for the initial thread.


Thanks,
Roland


nptl/
2007-05-16  Roland McGrath  <roland@redhat.com>

	* init.c (__nptl_initial_report_events): New variable.
	(__pthread_initialize_minimal_internal): Initialize pd->report_events
	to that.

nptl_db/
2007-05-16  Roland McGrath  <roland@redhat.com>

	* td_thr_get_info.c: Fake the results for TH->th_unique == 0.
	* td_thr_validate.c: Likewise.
	* td_thr_setgregs.c: Likewise.
	* td_thr_setfpregs.c: Likewise.
	* td_thr_getgregs.c: Likewise.
	* td_thr_getfpregs.c: Likewise.
	* td_thr_tlsbase.c: Likewise.

	* structs.def: Add DB_VARIABLE (__nptl_initial_report_events).
	* db_info.c: Add necessary declaration.
	* td_thr_event_enable.c: Set __nptl_initial_report_events too.

	* td_ta_thr_iter.c (iterate_thread_list): Make FAKE_EMPTY bool.
	Use th_unique=0 in fake descriptor before initialization.

	* td_ta_map_lwp2thr.c (__td_ta_lookup_th_unique): New function, broken
	out of ...
	(td_ta_map_lwp2thr): ... here, call it.  But don't before __stack_user
	is initialized, then fake a handle with th_unique=0.
	* thread_dbP.h: Declare it.

Index: nptl/init.c
===================================================================
RCS file: /cvs/glibc/libc/nptl/init.c,v
retrieving revision 1.60
diff -b -B -p -u -r1.60 init.c
--- nptl/init.c	27 Oct 2006 23:11:43 -0000	1.60
+++ nptl/init.c	17 May 2007 02:42:22 -0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -255,6 +255,9 @@ sighandler_setxid (int sig, siginfo_t *s
 extern void **__libc_dl_error_tsd (void) __attribute__ ((const));
 
 
+/* This can be set by the debugger before initialization is complete.  */
+static bool __nptl_initial_report_events;
+
 void
 __pthread_initialize_minimal_internal (void)
 {
@@ -306,6 +309,9 @@ __pthread_initialize_minimal_internal (v
   INIT_LIST_HEAD (&__stack_user);
   list_add (&pd->list, &__stack_user);
 
+  /* Before initializing __stack_user, the debugger could not find us and
+     had to set __nptl_initial_report_events.  Propagate its setting.  */
+  THREAD_SETMEM (pd, report_events, __nptl_initial_report_events);
 
   /* Install the cancellation signal handler.  If for some reason we
      cannot install the handler we do not abort.  Maybe we should, but
Index: nptl_db/db_info.c
===================================================================
RCS file: /cvs/glibc/libc/nptl_db/db_info.c,v
retrieving revision 1.6
diff -b -B -p -u -r1.6 db_info.c
--- nptl_db/db_info.c	31 Oct 2006 17:33:49 -0000	1.6
+++ nptl_db/db_info.c	17 May 2007 02:42:22 -0000
@@ -1,7 +1,7 @@
 /* This file is included by pthread_create.c to define in libpthread
    all the magic symbols required by libthread_db.
 
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -38,6 +38,8 @@ typedef struct
 
 typedef struct link_map link_map;
 
+/* Actually static in nptl/init.c, but we only need it for typeof.  */
+extern bool __nptl_initial_report_events;
 
 #define schedparam_sched_priority schedparam.sched_priority
 
Index: nptl_db/structs.def
===================================================================
RCS file: /cvs/glibc/libc/nptl_db/structs.def,v
retrieving revision 1.4
diff -b -B -p -u -r1.4 structs.def
--- nptl_db/structs.def	27 Oct 2006 23:11:44 -0000	1.4
+++ nptl_db/structs.def	17 May 2007 02:42:22 -0000
@@ -1,5 +1,5 @@
 /* List of types and symbols in libpthread examined by libthread_db.
-   Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -56,6 +56,7 @@ DB_FUNCTION (__nptl_death_event)
 DB_SYMBOL (__nptl_threads_events)
 DB_VARIABLE (__nptl_nthreads)
 DB_VARIABLE (__nptl_last_event)
+DB_VARIABLE (__nptl_initial_report_events)
 
 DB_ARRAY_VARIABLE (__pthread_keys)
 DB_STRUCT (pthread_key_struct)
Index: nptl_db/td_ta_map_lwp2thr.c
===================================================================
RCS file: /cvs/glibc/libc/nptl_db/td_ta_map_lwp2thr.c,v
retrieving revision 1.5
diff -b -B -p -u -r1.5 td_ta_map_lwp2thr.c
--- nptl_db/td_ta_map_lwp2thr.c	9 Sep 2004 22:50:10 -0000	1.5
+++ nptl_db/td_ta_map_lwp2thr.c	17 May 2007 02:42:22 -0000
@@ -1,5 +1,5 @@
 /* Which thread is running on an LWP?
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -24,7 +24,7 @@
 
 
 td_err_e
-td_ta_map_lwp2thr (const td_thragent_t *ta_arg,
+__td_ta_lookup_th_unique (const td_thragent_t *ta_arg,
 		   lwpid_t lwpid, td_thrhandle_t *th)
 {
   td_thragent_t *const ta = (td_thragent_t *) ta_arg;
@@ -118,9 +118,6 @@ td_ta_map_lwp2thr (const td_thragent_t *
 
   switch (ta->ta_howto)
     {
-    case ta_howto_unknown:
-      return TD_DBERR;
-
     default:
       return TD_DBERR;
 
@@ -143,7 +141,7 @@ td_ta_map_lwp2thr (const td_thragent_t *
       if (&ps_get_thread_area == NULL)
 	return TD_NOCAPAB;
 
-       /* A la x86-64, there is a constant magic index for get_thread_area.  */
+      /* A la x86-64, there is a magic index for get_thread_area.  */
        if (ps_get_thread_area (ta->ph, lwpid,
 			       ta->ta_howto_data.const_thread_area,
 			       &th->th_unique) != PS_OK)
@@ -154,11 +152,11 @@ td_ta_map_lwp2thr (const td_thragent_t *
       if (&ps_get_thread_area == NULL)
 	return TD_NOCAPAB;
 
-       /* A la i386, there is a register with an index for get_thread_area.  */
+      /* A la i386, a register holds the index for get_thread_area.  */
        if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK)
 	 return TD_ERR;
-       terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg_thread_area, -1,
-				     0, regs, &addr);
+      terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg_thread_area,
+				    -1, 0, regs, &addr);
       if (terr != TD_OK)
 	return terr;
       /* In this descriptor the nelem word is overloaded as scale factor.  */
@@ -172,7 +170,40 @@ td_ta_map_lwp2thr (const td_thragent_t *
     }
 
   /* Found it.  Now complete the `td_thrhandle_t' object.  */
-  th->th_ta_p = (td_thragent_t *) ta;
+  th->th_ta_p = ta;
 
   return TD_OK;
 }
+
+td_err_e
+td_ta_map_lwp2thr (const td_thragent_t *ta_arg,
+		   lwpid_t lwpid, td_thrhandle_t *th)
+{
+  td_thragent_t *const ta = (td_thragent_t *) ta_arg;
+
+  /* We cannot rely on thread registers and such information at all
+     before __pthread_initialize_minimal has gotten far enough.  They
+     sometimes contain garbage that would confuse us, left by the kernel
+     at exec.  So if it looks like initialization is incomplete, we only
+     fake a special descriptor for the initial thread.  */
+
+  psaddr_t list;
+  td_err_e err = DB_GET_SYMBOL (list, ta, __stack_user);
+  if (err != TD_OK)
+    return err;
+
+  err = DB_GET_FIELD (list, ta, list, list_t, next, 0);
+  if (err != TD_OK)
+    return err;
+
+  if (list == 0)
+    {
+      if (ps_getpid (ta->ph) != lwpid)
+	return TD_ERR;
+      th->th_ta_p = ta;
+      th->th_unique = 0;
+      return TD_OK;
+    }
+
+  return __td_ta_lookup_th_unique (ta_arg, lwpid, th);
+}
Index: nptl_db/td_ta_thr_iter.c
===================================================================
RCS file: /cvs/glibc/libc/nptl_db/td_ta_thr_iter.c,v
retrieving revision 1.8
diff -b -B -p -u -r1.8 td_ta_thr_iter.c
--- nptl_db/td_ta_thr_iter.c	4 Apr 2004 00:31:10 -0000	1.8
+++ nptl_db/td_ta_thr_iter.c	17 May 2007 02:42:22 -0000
@@ -1,5 +1,6 @@
 /* Iterate over a process's threads.
-   Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+   Copyright (C) 1999,2000,2001,2002,2003,2004,2007
+	Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
 
@@ -24,7 +25,7 @@
 static td_err_e
 iterate_thread_list (td_thragent_t *ta, td_thr_iter_f *callback,
 		     void *cbdata_p, td_thr_state_e state, int ti_pri,
-		     psaddr_t head, int fake_empty)
+		     psaddr_t head, bool fake_empty)
 {
   td_err_e err;
   psaddr_t next, ofs;
@@ -41,13 +42,13 @@ iterate_thread_list (td_thragent_t *ta, 
 
   if (next == 0 && fake_empty)
     {
-      /* __pthread_initialize_minimal has not run.
-	 There is just the main thread to return.  */
-      td_thrhandle_t th;
-      err = td_ta_map_lwp2thr (ta, ps_getpid (ta->ph), &th);
-      if (err == TD_OK)
-	err = callback (&th, cbdata_p) != 0 ? TD_DBERR : TD_OK;
-      return err;
+      /* __pthread_initialize_minimal has not run.  There is just the main
+	 thread to return.  We cannot rely on its thread register.  They
+	 sometimes contain garbage that would confuse us, left by the
+	 kernel at exec.  So if it looks like initialization is incomplete,
+	 we only fake a special descriptor for the initial thread.  */
+      td_thrhandle_t th = { ta, 0 };
+      return callback (&th, cbdata_p) != 0 ? TD_DBERR : TD_OK;
     }
 
   /* Cache the offset from struct pthread to its list_t member.  */
@@ -136,13 +137,15 @@ td_ta_thr_iter (const td_thragent_t *ta_
 
   err = DB_GET_SYMBOL (list, ta, __stack_user);
   if (err == TD_OK)
-    err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri, list, 1);
+    err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri,
+			       list, true);
 
   /* And the threads with stacks allocated by the implementation.  */
   if (err == TD_OK)
     err = DB_GET_SYMBOL (list, ta, stack_used);
   if (err == TD_OK)
-    err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri, list, 0);
+    err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri,
+			       list, false);
 
   return err;
 }
Index: nptl_db/td_thr_event_enable.c
===================================================================
RCS file: /cvs/glibc/libc/nptl_db/td_thr_event_enable.c,v
retrieving revision 1.3
diff -b -B -p -u -r1.3 td_thr_event_enable.c
--- nptl_db/td_thr_event_enable.c	9 Sep 2003 06:57:51 -0000	1.3
+++ nptl_db/td_thr_event_enable.c	17 May 2007 02:42:22 -0000
@@ -1,5 +1,5 @@
 /* Enable event process-wide.
-   Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2001, 2002, 2003, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
 
@@ -28,7 +28,25 @@ td_thr_event_enable (th, onoff)
 {
   LOG ("td_thr_event_enable");
 
+  if (th->th_unique != 0)
+    {
   /* Write the new value into the thread data structure.  */
-  return DB_PUT_FIELD (th->th_ta_p, th->th_unique, pthread, report_events, 0,
+      td_err_e err = DB_PUT_FIELD (th->th_ta_p, th->th_unique, pthread,
+				   report_events, 0,
+				   (psaddr_t) 0 + (onoff != 0));
+      if (err != TD_OK)
+	return err;
+
+      /* Just in case we are in the window between initializing __stack_user
+	 and copying from __nptl_initial_report_events, we set it too.
+	 It doesn't hurt to do this for non-initial threads, since it
+	 won't be consulted again anyway.  It would take another fetch
+	 to get the tid and determine this isn't the initial thread,
+	 so just do it always.  */
+    }
+
+  /* We are faking it for the initial thread before its thread
+     descriptor is set up.  */
+  return DB_PUT_VALUE (th->th_ta_p, __nptl_initial_report_events, 0,
 		       (psaddr_t) 0 + (onoff != 0));
 }
Index: nptl_db/td_thr_get_info.c
===================================================================
RCS file: /cvs/glibc/libc/nptl_db/td_thr_get_info.c,v
retrieving revision 1.6
diff -b -B -p -u -r1.6 td_thr_get_info.c
--- nptl_db/td_thr_get_info.c	9 Sep 2003 06:59:59 -0000	1.6
+++ nptl_db/td_thr_get_info.c	17 May 2007 02:42:22 -0000
@@ -1,5 +1,5 @@
 /* Get thread information.
-   Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999,2000,2001,2002,2003,2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
 
@@ -32,6 +32,19 @@ td_thr_get_info (const td_thrhandle_t *t
 
   LOG ("td_thr_get_info");
 
+  if (th->th_unique == 0)
+    {
+      /* Special case for the main thread before initialization.  */
+      copy = NULL;
+      tls = 0;
+      cancelhandling = 0;
+      schedprio = 0;
+      tid = 0;
+      err = DB_GET_VALUE (report_events, th->th_ta_p,
+			  __nptl_initial_report_events, 0);
+    }
+  else
+    {
   /* Copy the whole descriptor in once so we can access the several
      fields locally.  Excess copying in one go is much better than
      multiple ps_pdread calls.  */
@@ -61,6 +74,7 @@ td_thr_get_info (const td_thrhandle_t *t
     return err;
   err = DB_GET_FIELD_LOCAL (report_events, th->th_ta_p, copy, pthread,
 			    report_events, 0);
+    }
   if (err != TD_OK)
     return err;
 
@@ -87,9 +101,10 @@ td_thr_get_info (const td_thrhandle_t *t
   infop->ti_lid = tid == 0 ? ps_getpid (th->th_ta_p->ph) : (uintptr_t) tid;
   infop->ti_traceme = report_events != 0;
 
+  if (copy != NULL)
   err = DB_GET_FIELD_LOCAL (infop->ti_startfunc, th->th_ta_p, copy, pthread,
 			    start_routine, 0);
-  if (err == TD_OK)
+  if (copy != NULL && err == TD_OK)
     {
       uint32_t idx;
       for (idx = 0; idx < TD_EVENTSIZE; ++idx)
Index: nptl_db/td_thr_getfpregs.c
===================================================================
RCS file: /cvs/glibc/libc/nptl_db/td_thr_getfpregs.c,v
retrieving revision 1.3
diff -b -B -p -u -r1.3 td_thr_getfpregs.c
--- nptl_db/td_thr_getfpregs.c	9 Sep 2003 06:57:51 -0000	1.3
+++ nptl_db/td_thr_getfpregs.c	17 May 2007 02:42:22 -0000
@@ -1,5 +1,5 @@
 /* Get a thread's floating-point register set.
-   Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2001, 2002, 2003, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
 
@@ -29,6 +29,11 @@ td_thr_getfpregs (const td_thrhandle_t *
 
   LOG ("td_thr_getfpregs");
 
+  if (th->th_unique == 0)
+    /* Special case for the main thread before initialization.  */
+    return ps_lgetfpregs (th->th_ta_p->ph, ps_getpid (th->th_ta_p->ph),
+			  regset) != PS_OK ? TD_ERR : TD_OK;
+
   /* We have to get the state and the PID for this thread.  */
   err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread,
 		      cancelhandling, 0);
Index: nptl_db/td_thr_getgregs.c
===================================================================
RCS file: /cvs/glibc/libc/nptl_db/td_thr_getgregs.c,v
retrieving revision 1.3
diff -b -B -p -u -r1.3 td_thr_getgregs.c
--- nptl_db/td_thr_getgregs.c	9 Sep 2003 06:57:51 -0000	1.3
+++ nptl_db/td_thr_getgregs.c	17 May 2007 02:42:22 -0000
@@ -1,5 +1,5 @@
 /* Get a thread's general register set.
-   Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
 
@@ -29,6 +29,11 @@ td_thr_getgregs (const td_thrhandle_t *t
 
   LOG ("td_thr_getgregs");
 
+  if (th->th_unique == 0)
+    /* Special case for the main thread before initialization.  */
+    return ps_lgetregs (th->th_ta_p->ph, ps_getpid (th->th_ta_p->ph),
+			regset) != PS_OK ? TD_ERR : TD_OK;
+
   /* We have to get the state and the PID for this thread.  */
   err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread,
 		      cancelhandling, 0);
Index: nptl_db/td_thr_setfpregs.c
===================================================================
RCS file: /cvs/glibc/libc/nptl_db/td_thr_setfpregs.c,v
retrieving revision 1.3
diff -b -B -p -u -r1.3 td_thr_setfpregs.c
--- nptl_db/td_thr_setfpregs.c	9 Sep 2003 06:57:51 -0000	1.3
+++ nptl_db/td_thr_setfpregs.c	17 May 2007 02:42:22 -0000
@@ -1,5 +1,5 @@
 /* Set a thread's floating-point register set.
-   Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2001, 2002, 2003, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
 
@@ -29,6 +29,11 @@ td_thr_setfpregs (const td_thrhandle_t *
 
   LOG ("td_thr_setfpregs");
 
+  if (th->th_unique == 0)
+    /* Special case for the main thread before initialization.  */
+    return ps_lsetfpregs (th->th_ta_p->ph, ps_getpid (th->th_ta_p->ph),
+			  fpregs) != PS_OK ? TD_ERR : TD_OK;
+
   /* We have to get the state and the PID for this thread.  */
   err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread,
 		      cancelhandling, 0);
Index: nptl_db/td_thr_setgregs.c
===================================================================
RCS file: /cvs/glibc/libc/nptl_db/td_thr_setgregs.c,v
retrieving revision 1.3
diff -b -B -p -u -r1.3 td_thr_setgregs.c
--- nptl_db/td_thr_setgregs.c	9 Sep 2003 06:57:51 -0000	1.3
+++ nptl_db/td_thr_setgregs.c	17 May 2007 02:42:22 -0000
@@ -1,5 +1,5 @@
 /* Set a thread's general register set.
-   Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2001, 2002, 2003, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
 
@@ -29,6 +29,11 @@ td_thr_setgregs (const td_thrhandle_t *t
 
   LOG ("td_thr_setgregs");
 
+  if (th->th_unique == 0)
+    /* Special case for the main thread before initialization.  */
+    return ps_lsetregs (th->th_ta_p->ph, ps_getpid (th->th_ta_p->ph),
+			gregs) != PS_OK ? TD_ERR : TD_OK;
+
   /* We have to get the state and the PID for this thread.  */
   err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread,
 		      cancelhandling, 0);
Index: nptl_db/td_thr_tlsbase.c
===================================================================
RCS file: /cvs/glibc/libc/nptl_db/td_thr_tlsbase.c,v
retrieving revision 1.3
diff -b -B -p -u -r1.3 td_thr_tlsbase.c
--- nptl_db/td_thr_tlsbase.c	4 Feb 2006 00:47:58 -0000	1.3
+++ nptl_db/td_thr_tlsbase.c	17 May 2007 02:42:22 -0000
@@ -1,5 +1,5 @@
 /* Locate TLS data for a thread.
-   Copyright (C) 2003, 2006 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -30,8 +30,29 @@ td_thr_tlsbase (const td_thrhandle_t *th
   if (modid < 1)
     return TD_NOTLS;
 
+  psaddr_t pd = th->th_unique;
+  if (pd == 0)
+    {
+      /* This is the fake handle for the main thread before libpthread
+	 initialization.  We are using 0 for its th_unique because we can't
+	 trust that its thread register has been initialized.  But we need
+	 a real pointer to have any TLS access work.  In case of dlopen'd
+	 libpthread, initialization might not be for quite some time.  So
+	 try looking up the thread register now.  Worst case, it's nonzero
+	 uninitialized garbage and we get bogus results for TLS access
+	 attempted too early.  Tough.  */
+
+      td_thrhandle_t main_th;
+      err = __td_ta_lookup_th_unique (th->th_ta_p, ps_getpid (th->th_ta_p->ph),
+				      &main_th);
+      if (err == 0)
+	pd = main_th.th_unique;
+      if (pd == 0)
+	return TD_TLSDEFER;
+    }
+
   /* Get the DTV pointer from the thread descriptor.  */
-  err = DB_GET_FIELD (dtv, th->th_ta_p, th->th_unique, pthread, dtvp, 0);
+  err = DB_GET_FIELD (dtv, th->th_ta_p, pd, pthread, dtvp, 0);
   if (err != TD_OK)
     return err;
 
Index: nptl_db/td_thr_validate.c
===================================================================
RCS file: /cvs/glibc/libc/nptl_db/td_thr_validate.c,v
retrieving revision 1.4
diff -b -B -p -u -r1.4 td_thr_validate.c
--- nptl_db/td_thr_validate.c	1 Jun 2004 21:42:02 -0000	1.4
+++ nptl_db/td_thr_validate.c	17 May 2007 02:42:22 -0000
@@ -1,5 +1,5 @@
 /* Validate a thread handle.
-   Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1999,2001,2002,2003,2004,2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
 
@@ -75,16 +75,10 @@ td_thr_validate (const td_thrhandle_t *t
       if (err == TD_OK)
 	err = check_thread_list (th, list, &uninit);
 
-      if (err == TD_NOTHR && uninit)
-	{
+      if (err == TD_NOTHR && uninit && th->th_unique == 0)
 	  /* __pthread_initialize_minimal has not run yet.
-	     But the main thread still has a valid ID.  */
-	  td_thrhandle_t main_th;
-	  err = td_ta_map_lwp2thr (th->th_ta_p,
-				   ps_getpid (th->th_ta_p->ph), &main_th);
-	  if (err == TD_OK && th->th_unique != main_th.th_unique)
-	    err = TD_NOTHR;
-	}
+	   There is only the special case thread handle.  */
+	err = TD_OK;
     }
 
   return err;
Index: nptl_db/thread_dbP.h
===================================================================
RCS file: /cvs/glibc/libc/nptl_db/thread_dbP.h,v
retrieving revision 1.5
diff -b -B -p -u -r1.5 thread_dbP.h
--- nptl_db/thread_dbP.h	3 May 2004 21:30:30 -0000	1.5
+++ nptl_db/thread_dbP.h	17 May 2007 02:42:22 -0000
@@ -1,5 +1,5 @@
 /* Private header for thread debug library
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -251,4 +251,7 @@ extern td_err_e _td_store_value_local (t
 extern td_err_e _td_check_sizeof (td_thragent_t *ta, uint32_t *sizep,
 				  int sizep_name) attribute_hidden;
 
+extern td_err_e __td_ta_lookup_th_unique (const td_thragent_t *ta,
+					  lwpid_t lwpid, td_thrhandle_t *th);
+
 #endif /* thread_dbP.h */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]