Not yet submitted upstream.  This requires some serious thinking about. 
If the target stack worked in any logical way, this wouldn't be necessary...
ending up with roughly:
  thread_stratum: thread-db (silent reference to lin-lwp)
  core_stratum: corelow
  exec_stratum: exec
  dummy_stratum: dummy
just makes no sense.

This patch fixes debugging threaded applications which are statically linked
without breaking debugging threaded core files.  It also fixes the PIDs in
generate-core-file'd corefiles.  Mostly.

Index: gdb-2004-03-01-cvs/gdb/corelow.c
===================================================================
--- gdb-2004-03-01-cvs.orig/gdb/corelow.c	2004-03-01 12:34:18.000000000 -0500
+++ gdb-2004-03-01-cvs/gdb/corelow.c	2004-03-01 12:55:08.000000000 -0500
@@ -374,7 +374,7 @@ core_open (char *filename, int from_tty)
   bfd_map_over_sections (core_bfd, add_to_thread_list,
 			 bfd_get_section_by_name (core_bfd, ".reg"));
 
-  if (ontop)
+  if (ontop || 1)
     {
       /* Fetch all registers from core file.  */
       target_fetch_registers (-1);
Index: gdb-2004-03-01-cvs/gdb/thread-db.c
===================================================================
--- gdb-2004-03-01-cvs.orig/gdb/thread-db.c	2004-03-01 12:27:24.000000000 -0500
+++ gdb-2004-03-01-cvs/gdb/thread-db.c	2004-03-02 11:12:37.000000000 -0500
@@ -59,6 +59,40 @@ static void (*target_new_objfile_chain) 
 /* Non-zero if we're using this module's target vector.  */
 static int using_thread_db;
 
+/* Macros to pass an event to the next target if we should not be handling it
+   here in the thread_stratum.  */
+#define FIND_NEXT_TARGET(METHOD_NAME)			\
+  struct target_ops *next_target = &thread_db_ops;	\
+  while (1)						\
+    {							\
+      next_target = find_target_beneath (next_target);	\
+      if (next_target == NULL)				\
+	break;						\
+      if (next_target->METHOD_NAME != NULL)		\
+	break;						\
+    }
+
+#define MAYBE_HAND_DOWN(METHOD_NAME,ARGS,DEF)		\
+  if (proc_handle.pid == 0)				\
+    {							\
+      FIND_NEXT_TARGET (METHOD_NAME);			\
+      if (next_target == NULL)				\
+	{						\
+	  DEF;						\
+	  return;					\
+	}						\
+      (*next_target->METHOD_NAME) ARGS;			\
+      return;						\
+    }
+#define MAYBE_HAND_DOWN_RETURN(METHOD_NAME,ARGS,DEF)	\
+  if (proc_handle.pid == 0)				\
+    {							\
+      FIND_NEXT_TARGET (METHOD_NAME);			\
+      if (next_target == NULL)				\
+	DEF;						\
+      return (*next_target->METHOD_NAME) ARGS;		\
+    }
+
 /* Non-zero if we have to keep this module's target vector active
    across re-runs.  */
 static int keep_thread_db;
@@ -621,9 +655,7 @@ thread_db_new_objfile (struct objfile *o
       }
   }
 
-  /* Don't attempt to use thread_db on targets which can not run
-     (core files).  */
-  if (objfile == NULL || !target_has_execution)
+  if (objfile == NULL)
     {
       /* All symbols have been discarded.  If the thread_db target is
          active, deactivate it now.  */
@@ -647,7 +679,10 @@ thread_db_new_objfile (struct objfile *o
   /* Initialize the structure that identifies the child process.  Note
      that at this point there is no guarantee that we actually have a
      child process.  */
-  proc_handle.pid = GET_PID (inferior_ptid);
+  if (target_has_execution)
+    proc_handle.pid = GET_PID (inferior_ptid);
+  else
+    proc_handle.pid = 0;
 
   /* Now attempt to open a connection to the thread library.  */
   err = td_ta_new_p (&proc_handle, &thread_agent);
@@ -917,6 +952,10 @@ thread_db_xfer_memory (CORE_ADDR memaddr
   struct cleanup *old_chain = save_inferior_ptid ();
   int xfer;
 
+  MAYBE_HAND_DOWN_RETURN (to_xfer_memory, (memaddr, myaddr, len, write,
+					   attrib, target),
+			  noprocess ());
+
   if (is_thread (inferior_ptid))
     {
       /* FIXME: This seems to be necessary to make sure breakpoints
@@ -943,6 +982,10 @@ thread_db_fetch_registers (int regno)
   gdb_prfpregset_t fpregset;
   td_err_e err;
 
+  MAYBE_HAND_DOWN (to_fetch_registers, (regno), );
+
+  MAYBE_HAND_DOWN (to_store_registers, (regno), noprocess ());
+
   if (!is_thread (inferior_ptid))
     {
       /* Pass the request to the target beneath us.  */
@@ -1076,6 +1119,8 @@ thread_db_thread_alive (ptid_t ptid)
   td_thrhandle_t th;
   td_err_e err;
 
+  MAYBE_HAND_DOWN_RETURN (to_thread_alive, (ptid), return 0);
+
   if (is_thread (ptid))
     {
       struct thread_info *thread_info;
@@ -1140,6 +1185,8 @@ thread_db_find_new_threads (void)
 {
   td_err_e err;
 
+  MAYBE_HAND_DOWN (to_find_new_threads, (), );
+
   /* Iterate over all user-space threads to discover new threads.  */
   err = td_ta_thr_iter_p (thread_agent, find_new_threads_callback, NULL,
 			  TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
@@ -1151,6 +1198,8 @@ thread_db_find_new_threads (void)
 static char *
 thread_db_pid_to_str (ptid_t ptid)
 {
+  MAYBE_HAND_DOWN_RETURN (to_pid_to_str, (ptid), normal_pid_to_str (ptid));
+
   if (is_thread (ptid))
     {
       static char buf[64];
