From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28566 invoked by alias); 25 Jun 2009 23:47:41 -0000 Received: (qmail 28557 invoked by uid 22791); 25 Jun 2009 23:47:40 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL,BAYES_00 X-Spam-Check-By: sourceware.org Received: from mailhost.u-strasbg.fr (HELO mailhost.u-strasbg.fr) (130.79.200.158) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 25 Jun 2009 23:47:33 +0000 Received: from baal.u-strasbg.fr (baal.u-strasbg.fr [IPv6:2001:660:2402::41]) by mailhost.u-strasbg.fr (8.14.2/jtpda-5.5pre1) with ESMTP id n5PNlTGv011227 for ; Fri, 26 Jun 2009 01:47:29 +0200 (CEST) Received: from mailserver.u-strasbg.fr (ms1.u-strasbg.fr [IPv6:2001:660:2402:d::10]) by baal.u-strasbg.fr (8.14.0/jtpda-5.5pre1) with ESMTP id n5PNlTVp002234 for ; Fri, 26 Jun 2009 01:47:29 +0200 (CEST) (envelope-from muller@ics.u-strasbg.fr) Received: from d620muller (lec67-4-82-230-53-140.fbx.proxad.net [82.230.53.140]) (user=mullerp mech=LOGIN) by mailserver.u-strasbg.fr (8.14.3/jtpda-5.5pre1) with ESMTP id n5PNlS6U082223 (version=TLSv1/SSLv3 cipher=RC4-MD5 bits=128 verify=NO) for ; Fri, 26 Jun 2009 01:47:28 +0200 (CEST) (envelope-from muller@ics.u-strasbg.fr) From: "Pierre Muller" To: Subject: [RFC] Add windows Thread Information Block Date: Thu, 25 Jun 2009 23:47:00 -0000 Message-ID: <000901c9f5ef$4ee06f10$eca14d30$@u-strasbg.fr> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2009-06/txt/msg00697.txt.bz2 On windows operating system each thread gets a Thread Information Block which contains several interesting informations: - Current top of Structured Exception Handlers - Thread Variable allocations - Process information - Current limits of stack The last could be particularly interesting when we try to to figure out an optimized stack frame. When we hit a frameless function without debug information, we could try to find up the stack a valid pair of stored (EBP,EIP) of the outer frame having a frame pointer. Testing for EBP to bee within the limits given by current_top_of_stack andcurrent_bottom_of_stack would help to find correct pairs. I only tried to implement the 32bit version of this until now, the 64bit version has a different layout... More fields are available, some being version (or simulation layer) dependent... The current patch adds the code to windows-nat.c despite the fact that I added the thread_local_base field to both windows-nat.c and gdbserver/win32-low.c. To be also usable for a remote gdbserver, I would need to move that to windows-tdep.c But here I need advice on how to move the display_tib function to windows-tdep.c file, as it is currently using internal information of windows-nat.c thread_info struct. Also how should I handle the remote case? Should I add a new query, something like 'qTlb'? How should I call this from windows-tdep code? All comments welcomed! Pierre Muller Pascal language support maintainer for GDB 2009-06-26 Pierre Muller * windows-nat.c (thread_info): Add THREAD_LOCAL_BASE field. (windows_add_thread): Add TLB argument of type 'void *'. Assign TLB to new field THREAD_LOCAL_BASE of thread_info struct. (fake_create_process): Adapt windows_add_thread call. (get_windows_debug_event): Idem. (display_tib): New function. (display_current_tib): New function. (_initialize_windows_nat): Add 'information w32 tib' command. * gdbserver/win32-low.c (thread_info): Add THREAD_LOCAL_BASE field. (child_add_thread): Add TLB argument of type 'void *'. (get_child_debug_event): Adapt call to child_add_thread. Index: windows-nat.c =================================================================== RCS file: /cvs/src/src/gdb/windows-nat.c,v retrieving revision 1.195 diff -u -p -r1.195 windows-nat.c --- windows-nat.c 17 Jun 2009 18:44:23 -0000 1.195 +++ windows-nat.c 25 Jun 2009 23:27:34 -0000 @@ -140,6 +140,9 @@ static int debug_registers_used; static void windows_stop (ptid_t); static int windows_thread_alive (struct target_ops *, ptid_t); static void windows_kill_inferior (struct target_ops *); +static int windows_xfer_memory (CORE_ADDR memaddr, gdb_byte *our, int len, + int write, struct mem_attrib *mem, + struct target_ops *target); static void cygwin_set_dr (int i, CORE_ADDR addr); static void cygwin_set_dr7 (unsigned long val); @@ -155,6 +158,7 @@ typedef struct thread_info_struct struct thread_info_struct *next; DWORD id; HANDLE h; + CORE_ADDR thread_local_base; char *name; int suspended; int reload_context; @@ -165,6 +169,50 @@ thread_info; static thread_info thread_head; + +typedef struct thread_information_block + { + uint32_t current_seh; /* %fs:0x0000 */ + uint32_t current_top_of_stack; /* %fs:0x0004 */ + uint32_t current_bottom_of_stack; /* %fs:0x0008 */ + uint32_t sub_system_tib; /* %fs:0x000c */ + uint32_t fiber_data; /* %fs:0x0010 */ + uint32_t arbitrary_data_slot; /* %fs:0x0014 */ + uint32_t linear_address_tib; /* %fs:0x0018 */ + uint32_t environment_pointer; /* %fs:0x001c */ + uint32_t process_id; /* %fs:0x0020 */ + uint32_t current_thread_id; /* %fs:0x0024 */ + uint32_t thread_local_storage; /* %fs:0x0028 */ + uint32_t active_rpc_handle; /* %fs:0x002c */ + uint32_t process_environment_block; /* %fs:0x0030 */ + uint32_t last_error_number; /* %fs:0x0034 */ + } +thread_information; + +static const +char* TIB_NAME[] = + { + " current_seh ", /* %fs:0x0000 */ + " current_top_of_stack ", /* %fs:0x0004 */ + " current_bottom_of_stack ", /* %fs:0x0008 */ + " sub_system_tib ", /* %fs:0x000c */ + " fiber_data ", /* %fs:0x0010 */ + " arbitrary_data_slot ", /* %fs:0x0014 */ + " linear_address_tib ", /* %fs:0x0018 */ + " environment_pointer ", /* %fs:0x001c */ + " process_id ", /* %fs:0x0020 */ + " current_thread_id ", /* %fs:0x0024 */ + " thread_local_storage ", /* %fs:0x0028 */ + " active_rpc_handle ", /* %fs:0x002c */ + " process_environment_block ", /* %fs:0x0030 */ + " last_error_number " /* %fs:0x0034 */ + }; + +static const int +MAX_TIB = sizeof (TIB_NAME) / sizeof (char*); + + + /* The process and thread handles for the above context. */ static DEBUG_EVENT current_event; /* The current debug event from @@ -284,7 +332,7 @@ thread_rec (DWORD id, int get_context) /* Add a thread to the thread list. */ static thread_info * -windows_add_thread (ptid_t ptid, HANDLE h) +windows_add_thread (ptid_t ptid, HANDLE h, void *tlb) { thread_info *th; DWORD id; @@ -299,6 +347,7 @@ windows_add_thread (ptid_t ptid, HANDLE th = XZALLOC (thread_info); th->id = id; th->h = h; + th->thread_local_base = (CORE_ADDR) (uintptr_t) tlb; th->next = thread_head.next; thread_head.next = th; add_thread (ptid); @@ -984,6 +1033,57 @@ display_selectors (char * args, int from } } +/* Display thread information block of a given thread. */ +static int +display_tib (thread_info* th) +{ + thread_info tib; + + if (!th) + return 0; + if (th->thread_local_base) + { + if (windows_xfer_memory (th->thread_local_base, (gdb_byte *) &tib, + sizeof (tib), 0, NULL, NULL)) + { + DWORD* index = (DWORD *) &tib; + int i; + printf_filtered ("Thread Information Block 0x%lx at 0x%8lx\n", + th->id, + th->thread_local_base); + + for (i = 0; i < MAX_TIB; i++) + printf_filtered ("%s is 0x%08lx\n", TIB_NAME [i], index [i]); + } + else + return 0; + + } + return 1; +} + +/* Display thread information block of a thread specified by ARGS. + If ARGS is empty, display thread information block of current_thread + if current_thread is non NULL. + Otherwise ARGS is parsed and converted to a integer that should + be the windows ThreadID (not the internal GDB thread ID). */ +static void +display_current_tib (char * args, int from_tty) +{ + if (args) + { + thread_info* th; + DWORD id = (DWORD) parse_and_eval_long (args); + th = thread_rec (id, 1); + if (th) + display_tib (th); + else + printf_filtered ("%ld is not a valid ThreadId\n", id); + } + else if (current_thread) + display_tib (current_thread); +} + static struct cmd_list_element *info_w32_cmdlist = NULL; static void @@ -1181,9 +1281,11 @@ fake_create_process (void) /* We can not debug anything in that case. */ } main_thread_id = current_event.dwThreadId; - current_thread = windows_add_thread (ptid_build (current_event.dwProcessId, 0, - current_event.dwThreadId), - current_event.u.CreateThread.hThread); + current_thread = windows_add_thread ( + ptid_build (current_event.dwProcessId, 0, + current_event.dwThreadId), + current_event.u.CreateThread.hThread, + current_event.u.CreateThread.lpThreadLocalBase); return main_thread_id; } @@ -1357,7 +1459,9 @@ get_windows_debug_event (struct target_o retval = current_event.dwThreadId; th = windows_add_thread (ptid_build (current_event.dwProcessId, 0, current_event.dwThreadId), - current_event.u.CreateThread.hThread); + current_event.u.CreateThread.hThread, + current_event.u.CreateThread.lpThreadLocalBase); + break; case EXIT_THREAD_DEBUG_EVENT: @@ -1390,7 +1494,8 @@ get_windows_debug_event (struct target_o /* Add the main thread */ th = windows_add_thread (ptid_build (current_event.dwProcessId, 0, current_event.dwThreadId), - current_event.u.CreateProcessInfo.hThread); + current_event.u.CreateProcessInfo.hThread, + current_event.u.CreateProcessInfo.lpThreadLocalBase); retval = current_event.dwThreadId; break; @@ -2278,6 +2383,10 @@ Show whether to display kernel exception add_cmd ("selector", class_info, display_selectors, _("Display selectors infos."), &info_w32_cmdlist); + add_cmd ("tib", class_info, display_current_tib, + _("Display thread information block."), + &info_w32_cmdlist); + add_target (&windows_ops); deprecated_init_ui_hook = set_windows_aliases; }