* 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; +}