	* Makefile.in (server.o): Cause USE_THREAD_DB to be defined as
	appropriate.
	* remote-utils.c (decode_qGetTLSAddr_args, encode_qGetTLSAddr_result):
	New functions.
	* server.c (handle_query): Add support for qGetTLSAddr packet.
	* server.h (decode_qGetTLSAddr_args, encode_qGetTLSAddr_result)
	(get_thread_local_addr): Declare.
	* thread-db.c (get_thread_local_addr): New function.

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/Makefile.in,v
retrieving revision 1.27
diff -u -p -r1.27 Makefile.in
--- Makefile.in	16 Oct 2004 16:18:54 -0000	1.27
+++ Makefile.in	18 Nov 2004 20:45:49 -0000
@@ -246,6 +246,8 @@ proc-service.o: proc-service.c $(server_
 regcache.o: regcache.c $(server_h) $(regdef_h)
 remote-utils.o: remote-utils.c terminal.h $(server_h)
 server.o: server.c $(server_h)
+	$(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< @USE_THREAD_DB@
+
 target.o: target.c $(server_h)
 thread-db.o: thread-db.c $(server_h) $(gdb_proc_service_h)
 utils.o: utils.c $(server_h)
Index: remote-utils.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/remote-utils.c,v
retrieving revision 1.22
diff -u -p -r1.22 remote-utils.c
--- remote-utils.c	16 Oct 2004 17:42:00 -0000	1.22
+++ remote-utils.c	18 Nov 2004 20:45:49 -0000
@@ -721,6 +721,60 @@ decode_M_packet (char *from, CORE_ADDR *
   convert_ascii_to_int (&from[i++], to, *len_ptr);
 }
 
+int
+decode_qGetTLSAddr_args (char *buf, unsigned long *thread_id_ptr,
+                         unsigned long *offset_ptr, CORE_ADDR *lm_ptr)
+{
+  int i = 0;
+  char ch;
+
+  *thread_id_ptr = 0;
+  *offset_ptr = 0;
+  *lm_ptr = 0;
+
+  while ((ch = buf[i++]) && ch != ',')
+    {
+      *thread_id_ptr = *thread_id_ptr << 4;
+      *thread_id_ptr |= fromhex (ch) & 0x0f;
+    }
+
+  if (ch == 0)
+    return 0;
+
+  while ((ch = buf[i++]) && ch != ',')
+    {
+      *offset_ptr = *offset_ptr << 4;
+      *offset_ptr |= fromhex (ch) & 0x0f;
+    }
+
+  if (ch == 0)
+    return 0;
+
+  while ((ch = buf[i++]))
+    {
+      *lm_ptr = *lm_ptr << 4;
+      *lm_ptr |= fromhex (ch) & 0x0f;
+    }
+
+  if (ch == 0)
+    return 1;
+  else
+    return 0;
+}
+
+char *
+encode_qGetTLSAddr_result (char *buf, CORE_ADDR addr)
+{
+  int shft = sizeof (CORE_ADDR) * 8 - 4;
+  while (shft >= 0)
+    {
+      *buf++ = tohex ((addr >> shft) & 0x0f);
+      shft -= 4;
+    }
+  *buf = 0;
+  return buf;
+}
+
 /* Ask GDB for the address of NAME, and return it in ADDRP if found.
    Returns 1 if the symbol is found, 0 if it is not, -1 on error.  */
 
Index: server.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/server.c,v
retrieving revision 1.22
diff -u -p -r1.22 server.c
--- server.c	5 Mar 2004 03:44:27 -0000	1.22
+++ server.c	18 Nov 2004 20:45:49 -0000
@@ -142,6 +142,37 @@ handle_query (char *own_buf)
       return;
     }
 
+#ifdef USE_THREAD_DB
+  if (strncmp ("qGetTLSAddr:", own_buf, 12) == 0)
+    {
+      unsigned long thread_id, offset;
+      CORE_ADDR link_map_addr, tls_addr;
+      int status;
+
+      status = decode_qGetTLSAddr_args (own_buf + 12, &thread_id, &offset,
+                                        &link_map_addr);
+      if (!status)
+	{
+	  /* Malformed qGetTLSAddr packet.  */
+	  write_enn (own_buf);
+	  return;
+	}
+
+      status = get_thread_local_addr (thread_id, offset, link_map_addr,
+                                      &tls_addr);
+
+      if (!status)
+	{
+	  /* Unable to obtain thread local address.  */
+	  write_enn (own_buf);
+	  return;
+	}
+
+      encode_qGetTLSAddr_result (own_buf, tls_addr);
+      return;
+    }
+#endif
+
   /* Otherwise we didn't know what packet it was.  Say we didn't
      understand it.  */
   own_buf[0] = 0;
Index: server.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/server.h,v
retrieving revision 1.15
diff -u -p -r1.15 server.h
--- server.h	12 Mar 2004 20:51:21 -0000	1.15
+++ server.h	18 Nov 2004 20:45:49 -0000
@@ -147,6 +147,10 @@ void decode_m_packet (char *from, CORE_A
 void decode_M_packet (char *from, CORE_ADDR * mem_addr_ptr,
 		      unsigned int *len_ptr, char *to);
 
+int decode_qGetTLSAddr_args (char *buf, unsigned long *thread_id_ptr,
+                             unsigned long *offset_ptr, CORE_ADDR *lm_ptr);
+char * encode_qGetTLSAddr_result (char *buf, CORE_ADDR addr);
+
 int unhexify (char *bin, const char *hex, int count);
 int hexify (char *hex, const char *bin, int count);
 
@@ -178,4 +182,8 @@ void init_registers (void);
 		 ? (registers_length () + 32) \
 		 : 2000)
 
+/* Functions from thread-db.c.  */
+
+int get_thread_local_addr (unsigned long thread_id, unsigned long offset,
+                           CORE_ADDR link_map_addr, CORE_ADDR *tls_addr_ptr);
 #endif /* SERVER_H */
Index: thread-db.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/thread-db.c,v
retrieving revision 1.2
diff -u -p -r1.2 thread-db.c
--- thread-db.c	16 Oct 2004 17:42:00 -0000	1.2
+++ thread-db.c	18 Nov 2004 20:45:49 -0000
@@ -366,3 +366,27 @@ thread_db_init ()
 
   return 0;
 }
+
+int
+get_thread_local_addr (unsigned long thread_id, unsigned long offset,
+                       CORE_ADDR link_map_addr, CORE_ADDR *tls_addr_ptr)
+{
+  td_thrhandle_t thread_handle;
+  td_err_e status;
+  void *addr;
+
+  status = td_ta_map_id2thr (thread_agent, (thread_t) thread_id,
+                             &thread_handle);
+
+  if (status != TD_OK)
+    return 0;
+
+  status = td_thr_tls_get_addr (&thread_handle, (void *) (long) link_map_addr,
+                                (size_t) offset, &addr);
+  *tls_addr_ptr = (CORE_ADDR) (long) addr;
+
+  if (status != TD_OK)
+    return 0;
+  else
+    return 1;
+}
