This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB 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]

[PING] [RFC-v3] Add windows Thread Information Block


Despite all my efforts,
I never managed to get advices on the non-windows part of
this patch :(
 
  I appended at the bottom of this email an
updated patch.
  To refresh memories,
this patch enables looking at the 'Thread Local Base'
an internal Windows structure describing the current thread
and some process wide features.
  The main problem was about my use of TARGET_OBJECT_OSDATA
to get this information from the gdbserver, which did not seem
to be compatible with the general usage of TARGET_OBJECT_OSDATA.

  I would really like to get new feedback on that
issue.

Pierre Muller
  

> -----Message d'origine-----
> De?: gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] De la part de Christopher Faylor
> Envoyé?: Friday, July 03, 2009 9:42 PM
> À?: gdb-patches@sourceware.org
> Objet?: Re: [RFC-v3] Add windows Thread Information Block
> 
> On Fri, Jul 03, 2009 at 06:11:41PM +0200, Pierre Muller wrote:
> >
> >  Here is a new version of this patch:
> >
> >  - It does add a convenience variable name "$_tlb"
> >for "thread local base" as this is the only value that needs
> >to be fetch especially.
> >   Maybe "_tib" is better, in the sense that it "talks" more to
> >windows used debuggers? But this is really only a pointer and not the
> >block itself. Any better idea?
> >
> >  I tried to create a type that really fits
> >the Windows OS layout, but as this structure is not documented really
> >and has changed between OS version, there can be no
> >assurance that all fields are OK in all versions...
> >  It works both native and remotely.
> >
> > I didn't check if it works OK, if endianess are different
> >but the extra field in extract_unsigned_integer should take care
> >of this.
> >
> >  As Christopher reported problems trying to apply my previous
> >version, I attach it this time, hoping that this will avoid troubles.
> >
> >  Pedro, I didn't change the TARGET_OBJECT type,
> >and I really want to know if this is really required,
> >as it seems to be a lot of work and I can't see the benefit...
> 
> Approved (for the parts that I can approve).
> 
> cgf


2009-07-03  Pierre Muller  <muller@ics.u-strasbg.fr>

	* windows-nat.c (thread_info): Add THREAD_LOCAL_BASE field.
	(windows_add_thread): Add TLB argument of type 'void *'.
	(fake_create_process): Adapt windows_add_thread call.
	(get_windows_debug_event): Idem.
	(windows_xfer_partial): Handle TARGET_OBJECT_OSDATA type.
	(_initialize_windows_nat): Replace info_w32_cmdlist
	initialization by a call to init_w32_command_list.
	(info_w32_command, info_w32_cmdlist): Removed from here...
	to windows-tdep.c file.
	*  windows-tdep.h (info_w32_cmdlist): Declare.
	(init_w32_command_list): New external function 
	declaration.	
	* windows-tdep.c: Add several headers.
	(info_w32_cmdlist): to here, made global.
	(thread_information_32): New struct.
	(thread_information_64): New struct.
	(TIB_NAME): New char array.
	(MAX_TIB32, MAX_TIB64, FULL_TIB_SIZE): New constants.
	(maint_display_all_tib): New static variable.
	(windows_get_tlb_type): New function.
	(tlb_value_read, tlb_value_write): New functions.
	(tlb_value_funcs): New static struct.
	(tlb_make_value): New function.
	(display_one_tib): New function.
	(display_tib): New function.
	(info_w32_command): Moved from windows-nat.c.
	(init_w32_command_list): New function.
	(_initialize_windows_tdep): New function.
	New "maint set/show show-all-tib" command
	New "$_tlb" internal variable.
	
gdbserver/ChangeLog entry:

2009-07-01  Pierre Muller  <muller@ics.u-strasbg.fr>

	* gdbserver/win32-low.h (win32_thread_info): Add THREAD_LOCAL_BASE 
	field.
	* gdbserver/win32-low.c (child_add_thread): Add TLB argument.
	(get_child_debug_event): Adapt to child_add_thread change.
	(win32_qxfer_osdata): New function.
	(win32_target_op): Set qxfer_osdata field to win32_qxfer_osdata.


Index: windows-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/windows-nat.c,v
retrieving revision 1.207
diff -u -p -r1.207 windows-nat.c
--- windows-nat.c	10 Mar 2010 15:57:07 -0000	1.207
+++ windows-nat.c	10 Mar 2010 16:51:00 -0000
@@ -191,6 +191,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;
@@ -320,7 +321,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;
@@ -335,6 +336,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);
@@ -1074,15 +1076,6 @@ display_selectors (char * args, int from
     }
 }
 
-static struct cmd_list_element *info_w32_cmdlist = NULL;
-
-static void
-info_w32_command (char *args, int from_tty)
-{
-  help_list (info_w32_cmdlist, "info w32 ", class_info, gdb_stdout);
-}
-
-
 #define DEBUG_EXCEPTION_SIMPLE(x)       if (debug_exceptions) \
   printf_unfiltered ("gdb: Target exception %s at %s\n", x, \
     host_address_to_string (\
@@ -1271,9 +1264,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;
 }
 
@@ -1447,7 +1442,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:
@@ -1481,7 +1478,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;
 
@@ -2243,6 +2241,11 @@ windows_xfer_partial (struct target_ops 
 		    const char *annex, gdb_byte *readbuf,
 		    const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
 {
+  ULONGEST val;
+  thread_info *th;
+  char info_type[20];
+  char *type_end;
+
   switch (object)
     {
     case TARGET_OBJECT_MEMORY:
@@ -2254,6 +2257,31 @@ windows_xfer_partial (struct target_ops 
 					       len, 1/*write*/, NULL, ops);
       return -1;
 
+    case TARGET_OBJECT_OSDATA:
+      memset (info_type, 0, sizeof (info_type));
+      val = 0;
+      sscanf (annex, "%s %llu", info_type, &val);
+      if (strcmp (info_type, "tlb") == 0  && readbuf)
+	{
+	  th = thread_rec (val, 0);
+	  if (th == NULL)
+	    return -1;
+
+	  if (len == 8)
+	    {
+	      uint64_t tlb = th->thread_local_base;
+	      memcpy ((void *)readbuf, (void *) &tlb, len);
+	      return len;
+	    }
+          else if (len == 4)
+	    {
+	      uint32_t tlb = th->thread_local_base;
+	      memcpy ((void *)readbuf, (void *) &tlb, len);
+	      return len;
+	    }
+	}
+      return -1;
+
     case TARGET_OBJECT_LIBRARIES:
       return windows_xfer_shared_libraries (ops, object, annex, readbuf,
 					  writebuf, offset, len);
@@ -2315,8 +2343,10 @@ init_windows_ops (void)
   windows_ops.to_pid_to_exec_file = windows_pid_to_exec_file;
   windows_ops.to_get_ada_task_ptid = windows_get_ada_task_ptid;
 
+#ifndef __USE_OLD_CYGWIN_API_
   i386_use_watchpoints (&windows_ops);
 
+#endif
   i386_dr_low.set_control = cygwin_set_dr7;
   i386_dr_low.set_addr = cygwin_set_dr;
   i386_dr_low.reset_addr = NULL;
@@ -2343,8 +2373,10 @@ _initialize_windows_nat (void)
   init_windows_ops ();
 
 #ifdef __CYGWIN__
+#ifdef __USEWIDE
   cygwin_internal (CW_SET_DOS_FILE_WARNING, 0);
 #endif
+#endif
 
   c = add_com ("dll-symbols", class_files, dll_symbol_command,
 	       _("Load dll library symbols from FILE."));
@@ -2415,9 +2447,7 @@ Show whether to display kernel exception
 			   NULL, /* FIXME: i18n: */
 			   &setlist, &showlist);
 
-  add_prefix_cmd ("w32", class_info, info_w32_command,
-		  _("Print information specific to Win32 debugging."),
-		  &info_w32_cmdlist, "info w32 ", 0, &infolist);
+  init_w32_command_list ();
 
   add_cmd ("selector", class_info, display_selectors,
 	   _("Display selectors infos."),
Index: windows-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/windows-tdep.c,v
retrieving revision 1.5
diff -u -p -r1.5 windows-tdep.c
--- windows-tdep.c	1 Jan 2010 07:31:46 -0000	1.5
+++ windows-tdep.c	10 Mar 2010 16:51:01 -0000
@@ -19,6 +19,356 @@
 #include "windows-tdep.h"
 #include "gdb_obstack.h"
 #include "xml-support.h"
+#include "gdbarch.h"
+#include "target.h"
+#include "value.h"
+#include "inferior.h"
+#include "command.h"
+#include "gdbcmd.h"
+
+struct cmd_list_element *info_w32_cmdlist;
+
+typedef struct thread_information_block_32
+  {
+    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_32;
+
+typedef struct thread_information_block_64
+  {
+    uint64_t current_seh;			/* %gs:0x0000 */
+    uint64_t current_top_of_stack; 		/* %gs:0x0008 */
+    uint64_t current_bottom_of_stack;		/* %gs:0x0010 */
+    uint64_t sub_system_tib;			/* %gs:0x0018 */
+    uint64_t fiber_data;			/* %gs:0x0020 */
+    uint64_t arbitrary_data_slot;		/* %gs:0x0028 */
+    uint64_t linear_address_tib;		/* %gs:0x0030 */
+  }
+thread_information_64;
+
+
+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_TIB32 = sizeof (thread_information_32) / sizeof (uint32_t);
+static const int
+MAX_TIB64 = sizeof (thread_information_64) / sizeof (uint64_t);
+static const int
+FULL_TIB_SIZE = 0x1000;
+
+static int maint_display_all_tib = 0;
+
+/* Define ThreadLocalBase pointer type */
+struct type *
+windows_get_tlb_type (struct gdbarch *gdbarch)
+{
+  struct type *dword_ptr_type, *void_ptr_type;
+  struct type *peb_ldr_type, *peb_ldr_ptr_type;
+  struct type *peb_type, *peb_ptr_type, *list_type, *list_ptr_type;
+  struct type *module_list_ptr_type;
+  struct type *tib_type, *seh_type, *tib_ptr_type, *seh_ptr_type;
+
+  dword_ptr_type = arch_integer_type (gdbarch, gdbarch_ptr_bit (gdbarch),
+				 1, "DWORD_PTR");
+  void_ptr_type = lookup_pointer_type (builtin_type
(gdbarch)->builtin_void);
+
+  /* list entry */
+
+  list_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
+  TYPE_NAME (list_type) = xstrdup ("list");
+
+  list_ptr_type = arch_type (gdbarch, TYPE_CODE_PTR,
+			    TYPE_LENGTH (void_ptr_type), NULL);
+
+  module_list_ptr_type = void_ptr_type;
+
+  append_composite_type_field (list_type, "forward_list",
module_list_ptr_type);
+  append_composite_type_field (list_type, "backward_list",
+			       module_list_ptr_type);
+
+  /* Structured Exception Handler */
+
+  seh_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
+  TYPE_NAME (seh_type) = xstrdup ("seh");
+
+  seh_ptr_type = arch_type (gdbarch, TYPE_CODE_PTR,
+			    TYPE_LENGTH (void_ptr_type), NULL);
+  TYPE_TARGET_TYPE (seh_ptr_type) = seh_type;
+
+  append_composite_type_field (seh_type, "next_seh", seh_ptr_type);
+  append_composite_type_field (seh_type, "handler", void_ptr_type);
+
+  /* struct _PEB_LDR_DATA */
+  /* FIXME: 64bit layout is unknown.  */
+  peb_ldr_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
+  TYPE_NAME (peb_ldr_type) = xstrdup ("peb_ldr_data");
+
+  append_composite_type_field (peb_ldr_type, "length", dword_ptr_type);
+  append_composite_type_field (peb_ldr_type, "initialized",
dword_ptr_type);
+  append_composite_type_field (peb_ldr_type, "ss_handle", void_ptr_type);
+  append_composite_type_field (peb_ldr_type, "in_load_order", list_type);
+  append_composite_type_field (peb_ldr_type, "in_memory_order", list_type);
+  append_composite_type_field (peb_ldr_type, "in_init_order", list_type);
+  append_composite_type_field (peb_ldr_type, "entry_in_progress",
+			       void_ptr_type);
+  peb_ldr_ptr_type = arch_type (gdbarch, TYPE_CODE_PTR,
+			    TYPE_LENGTH (void_ptr_type), NULL);
+  TYPE_TARGET_TYPE (peb_ldr_ptr_type) = peb_ldr_type;
+
+
+  /* struct process environment block */
+  peb_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
+  TYPE_NAME (peb_type) = xstrdup ("peb");
+
+  /* 4 first byte contain several flags.  */
+  /* FIXME: 64bit layout is unknown.  */
+  append_composite_type_field (peb_type, "flags", dword_ptr_type);
+  append_composite_type_field (peb_type, "mutant", void_ptr_type);
+  append_composite_type_field (peb_type, "image_base_address",
void_ptr_type);
+  append_composite_type_field (peb_type, "ldr", peb_ldr_ptr_type);
+  append_composite_type_field (peb_type, "process_parameters",
void_ptr_type);
+  append_composite_type_field (peb_type, "sub_system_data", void_ptr_type);
+  append_composite_type_field (peb_type, "process_heap", void_ptr_type);
+  append_composite_type_field (peb_type, "fast_peb_lock", void_ptr_type);
+  peb_ptr_type = arch_type (gdbarch, TYPE_CODE_PTR,
+			    TYPE_LENGTH (void_ptr_type), NULL);
+  TYPE_TARGET_TYPE (peb_ptr_type) = peb_type;
+
+
+  /* struct thread information block */
+  tib_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT);
+  TYPE_NAME (tib_type) = xstrdup ("tib");
+
+  /* uint32_t current_seh;			%fs:0x0000 */
+  append_composite_type_field (tib_type, "current_seh", seh_ptr_type);
+  /* uint32_t current_top_of_stack; 		%fs:0x0004 */
+  append_composite_type_field (tib_type, "current_top_of_stack",
void_ptr_type);
+  /* uint32_t current_bottom_of_stack;		%fs:0x0008 */
+  append_composite_type_field (tib_type, "current_bottom_of_stack",
+			       void_ptr_type);
+  /* uint32_t sub_system_tib;			%fs:0x000c */
+  append_composite_type_field (tib_type, "sub_system_tib", void_ptr_type);
+
+  /* uint32_t fiber_data;			%fs:0x0010 */
+  append_composite_type_field (tib_type, "fiber_data", void_ptr_type);
+  /* uint32_t arbitrary_data_slot;		%fs:0x0014 */
+  append_composite_type_field (tib_type, "arbitrary_data_slot",
void_ptr_type);
+  /* uint32_t linear_address_tib;		%fs:0x0018 */
+  append_composite_type_field (tib_type, "linear_address_tib",
void_ptr_type);
+  /* uint32_t environment_pointer;		%fs:0x001c */
+  append_composite_type_field (tib_type, "environment_pointer",
void_ptr_type);
+  /* uint32_t process_id;			%fs:0x0020 */
+  append_composite_type_field (tib_type, "process_id", dword_ptr_type);
+  /* uint32_t current_thread_id;		%fs:0x0024 */
+  append_composite_type_field (tib_type, "thread_id", dword_ptr_type);
+  /* uint32_t thread_local_storage;		%fs:0x0028 */
+  append_composite_type_field (tib_type, "thread_local_storage",
void_ptr_type);
+  /* uint32_t active_rpc_handle;		%fs:0x002c */
+  append_composite_type_field (tib_type, "active_rpc_handle",
dword_ptr_type);
+  /* uint32_t process_environment_block;	%fs:0x0030 */
+  append_composite_type_field (tib_type, "process_environment_block",
+			       peb_ptr_type);
+  /* uint32_t last_error_number;		%fs:0x0034 */
+  append_composite_type_field (tib_type, "last_error_number",
dword_ptr_type);
+
+  tib_ptr_type = arch_type (gdbarch, TYPE_CODE_PTR,
+			    TYPE_LENGTH (void_ptr_type), NULL);
+  TYPE_TARGET_TYPE (tib_ptr_type) = tib_type;
+
+  return tib_ptr_type;
+}
+/* The $_tlb convenience variable is a bit special.  We don't know
+   for sure the type of the value until we actually have a chance to
+   fetch the data.  The type can change depending on gdbarch, so it it
+   also dependent on which thread you have selected.
+
+     1. making $_tlb be an internalvar that creates a new value on
+     access.
+
+     2. making the value of $_tlbi be an lval_computed value.  */
+
+/* This function implements the lval_computed support for reading a
+   $_tlb value.  */
+
+static void
+tlb_value_read (struct value *v)
+{
+  LONGEST transferred;
+  char annex[20];
+  /* This needs to be changed if multi-process support is added.  */
+  strcpy (annex, "tlb ");
+  strcat (annex, pulongest (ptid_get_tid (inferior_ptid)));
+
+  transferred =
+    target_read (&current_target, TARGET_OBJECT_OSDATA,
+		 annex,
+		 value_contents_all_raw (v),
+		 value_offset (v),
+		 TYPE_LENGTH (value_type (v)));
+ 
+  if (transferred != TYPE_LENGTH (value_type (v)))
+    error (_("Unable to read tlb"));
+}
+
+/* This function implements the lval_computed support for writing a
+   $_siginfo value.  */
+
+static void
+tlb_value_write (struct value *v, struct value *fromval)
+{
+  error (_("Impossible to change tlb"));
+}
+
+static struct lval_funcs tlb_value_funcs =
+  {
+    tlb_value_read,
+    tlb_value_write
+  };
+
+
+/* Return a new value with the correct type for the tlb object of
+   the current thread using architecture GDBARCH.  Return a void value
+   if there's no object available.  */
+
+static struct value *
+tlb_make_value (struct gdbarch *gdbarch, struct internalvar *var)
+{
+  if (target_has_stack
+      && !ptid_equal (inferior_ptid, null_ptid))
+    {
+      struct type *type = windows_get_tlb_type (gdbarch);
+      return allocate_computed_value (type, &tlb_value_funcs, NULL);
+    }
+
+  return allocate_value (builtin_type (gdbarch)->builtin_void);
+}
+
+
+/* Display thread information block of a given thread.  */
+static int
+display_one_tib (ULONGEST ThreadId)
+{
+#define PTID_STRING_SIZE 40
+  char annex[PTID_STRING_SIZE];
+  char *annex_end = annex + PTID_STRING_SIZE;
+  gdb_byte *tib = NULL;
+  gdb_byte *index;
+  CORE_ADDR thread_local_base;
+  ULONGEST i, val, max, max_name, size, tib_size;
+  ULONGEST sizeof_ptr = gdbarch_ptr_bit (target_gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
+
+  if (sizeof_ptr == 64)
+    {
+      size = sizeof (uint64_t);
+      tib_size = sizeof (thread_information_64);
+      max = MAX_TIB64;
+    }
+  else
+    {
+      size = sizeof (uint32_t);
+      tib_size = sizeof (thread_information_32);
+      max = MAX_TIB32;
+    }
+
+  max_name = max;
+
+  if (maint_display_all_tib)
+    {
+      tib_size = FULL_TIB_SIZE;
+      max = tib_size / size;
+    }
+  
+  tib = alloca (tib_size);
+
+  /* This needs to be changed if multi-process support is added.  */
+  strcpy (annex, "tlb ");
+  strcat (annex, pulongest (ThreadId));
+
+  if (target_read (&current_target, TARGET_OBJECT_OSDATA,
+		   annex, tib, 0, size) != size)
+    {
+      printf_filtered ("Unable to get thread local base for ThreadId %s\n",
+	pulongest (ThreadId));
+      return -1;
+    }
+  thread_local_base = extract_unsigned_integer (tib, size, byte_order);
+
+  if (target_read (&current_target, TARGET_OBJECT_MEMORY,
+		   annex, tib, thread_local_base, tib_size) != tib_size)
+    {
+      printf_filtered ("Unable to read thread information block for
ThreadId %s at address %s\n",
+	pulongest (ThreadId), paddress (target_gdbarch, thread_local_base));
+      return -1;
+    }
+
+  printf_filtered ("Thread Information Block %s at %s\n",
+		   pulongest (ThreadId),
+		   paddress (target_gdbarch, thread_local_base));
+
+  index = (gdb_byte *) tib;
+
+  /* All fields have the size of a pointer, this allows to iterate 
+     using the same for loop for both layouts.  */
+  for (i = 0; i < max; i++)
+    {
+      val = extract_unsigned_integer (index, size, byte_order);
+      if (i < max_name)
+	printf_filtered ("%s is 0x%s\n", TIB_NAME [i], phex (val, size));
+      else if (val != 0)
+	printf_filtered ("TIB[0x%s] is 0x%s\n", phex (i*size, 2),
+			 phex (val, size));
+      index += size;
+    } 
+  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_tib (char * args, int from_tty)
+{
+  if (args)
+    {
+      ULONGEST id = (ULONGEST) parse_and_eval_long (args);
+      display_one_tib (id);
+    }
+  else if (!ptid_equal (inferior_ptid, null_ptid))
+    display_one_tib (ptid_get_tid (inferior_ptid));
+}
 
 void
 windows_xfer_shared_library (const char* so_name, CORE_ADDR load_addr,
@@ -36,3 +386,51 @@ windows_xfer_shared_library (const char*
   obstack_grow_str (obstack, paddress (gdbarch, load_addr + 0x1000));
   obstack_grow_str (obstack, "\"/></library>");
 }
+
+static void
+info_w32_command (char *args, int from_tty)
+{
+  help_list (info_w32_cmdlist, "info w32 ", class_info, gdb_stdout);
+}
+
+static int w32_prefix_command_valid = 0;
+void
+init_w32_command_list (void)
+{
+  if (!w32_prefix_command_valid)
+    {
+      add_prefix_cmd ("w32", class_info, info_w32_command,
+		      _("Print information specific to Win32 debugging."),
+		      &info_w32_cmdlist, "info w32 ", 0, &infolist);
+      w32_prefix_command_valid = 1;
+    }
+}
+
+void
+_initialize_windows_tdep (void)
+{
+  init_w32_command_list ();
+  add_cmd ("thread-information-block", class_info, display_tib,
+	   _("Display thread information block."),
+	   &info_w32_cmdlist);
+  add_alias_cmd ("tib", "thread-information-block", class_info, 1,
+		 &info_w32_cmdlist);
+
+  add_setshow_boolean_cmd ("show-all-tib", class_maintenance,
+			   &maint_display_all_tib, _("\
+Set whether to display all non-zero fields of thread information block."),
_("\
+Show whether to display all non-zero fields of thread information block."),
_("\
+Use \"on\" to enable, \"off\" to disable.\n\
+If enabled, all non-zero fields of thread information block are
displayed,\n\
+even if its meaning is unknown."),
+			   NULL,
+			   NULL,
+			   &maintenance_set_cmdlist,
+			   &maintenance_show_cmdlist);
+
+  /* Explicitly create without lookup, since that tries to create a
+     value with a void typed value, and when we get here, gdbarch
+     isn't initialized yet.  At this point, we're quite sure there
+     isn't another convenience variable of the same name.  */
+  create_internalvar_type_lazy ("_tlb", tlb_make_value);
+}
Index: windows-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/windows-tdep.h,v
retrieving revision 1.4
diff -u -p -r1.4 windows-tdep.h
--- windows-tdep.h	1 Jan 2010 07:31:46 -0000	1.4
+++ windows-tdep.h	10 Mar 2010 16:51:01 -0000
@@ -21,6 +21,10 @@
 struct obstack;
 struct gdbarch;
 
+extern struct cmd_list_element *info_w32_cmdlist;
+
+extern void init_w32_command_list (void);
+
 extern void windows_xfer_shared_library (const char* so_name,
 					 CORE_ADDR load_addr,
 					 struct gdbarch *gdbarch,
Index: gdbserver/win32-low.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/win32-low.c,v
retrieving revision 1.43
diff -u -p -r1.43 win32-low.c
--- gdbserver/win32-low.c	20 Jan 2010 22:55:38 -0000	1.43
+++ gdbserver/win32-low.c	10 Mar 2010 16:51:01 -0000
@@ -178,7 +178,7 @@ thread_rec (ptid_t ptid, int get_context
 
 /* Add a thread to the thread list.  */
 static win32_thread_info *
-child_add_thread (DWORD pid, DWORD tid, HANDLE h)
+child_add_thread (DWORD pid, DWORD tid, HANDLE h, void *tlb)
 {
   win32_thread_info *th;
   ptid_t ptid = ptid_build (pid, tid, 0);
@@ -189,6 +189,7 @@ child_add_thread (DWORD pid, DWORD tid, 
   th = xcalloc (1, sizeof (*th));
   th->tid = tid;
   th->h = h;
+  th->thread_local_base = (CORE_ADDR) (uintptr_t) tlb;
 
   add_thread (ptid, th);
   set_inferior_regcache_data ((struct thread_info *)
@@ -1449,7 +1450,8 @@ get_child_debug_event (struct target_wai
       /* Record the existence of this thread.  */
       child_add_thread (current_event.dwProcessId,
 			current_event.dwThreadId,
-			current_event.u.CreateThread.hThread);
+			current_event.u.CreateThread.hThread,
+			current_event.u.CreateThread.lpThreadLocalBase);
       break;
 
     case EXIT_THREAD_DEBUG_EVENT:
@@ -1479,7 +1481,8 @@ get_child_debug_event (struct target_wai
       /* Add the main thread.  */
       child_add_thread (current_event.dwProcessId,
 			main_thread_id,
-			current_event.u.CreateProcessInfo.hThread);
+			current_event.u.CreateProcessInfo.hThread,
+
current_event.u.CreateProcessInfo.lpThreadLocalBase);
 
       ourstatus->value.related_pid = debug_event_ptid (&current_event);
 #ifdef _WIN32_WCE
@@ -1750,6 +1753,42 @@ wince_hostio_last_error (char *buf)
 }
 #endif
 
+/* Read/Write Windows OS information.  */
+int
+win32_qxfer_osdata (const char *info_type,
+		    unsigned char *readbuf, unsigned const char *writebuf,
+		    CORE_ADDR offset, int len)
+
+{
+  if (strncmp (info_type, "tlb ", 4) == 0 && readbuf)
+    {
+      unsigned long long tid;
+      char type_name[20];
+      ptid_t ptid;
+      win32_thread_info *th;
+      sscanf (info_type, "%s %llu", type_name, &tid);
+      ptid = ptid_build (current_process_id, tid, 0);
+      th = thread_rec (ptid, 0);
+      if (th == NULL)
+	return 0;
+      len--;
+      if (len == 8)
+	{
+	  uint64_t tlb = th->thread_local_base;
+	  memcpy (readbuf, &tlb, len);
+	  return len;
+	}
+      else if (len == 4)
+	{
+	  uint32_t tlb = th->thread_local_base;
+	  memcpy (readbuf, &tlb, len);
+	  return len;
+	}
+    }
+  return -1;
+}
+
+
 static struct target_ops win32_target_ops = {
   win32_create_inferior,
   win32_attach,
@@ -1778,6 +1817,7 @@ static struct target_ops win32_target_op
 #else
   hostio_last_error_from_errno,
 #endif
+  win32_qxfer_osdata,
 };
 
 /* Initialize the Win32 backend.  */
Index: gdbserver/win32-low.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/win32-low.h,v
retrieving revision 1.12
diff -u -p -r1.12 win32-low.h
--- gdbserver/win32-low.h	20 Jan 2010 22:55:38 -0000	1.12
+++ gdbserver/win32-low.h	10 Mar 2010 16:51:01 -0000
@@ -28,6 +28,9 @@ typedef struct win32_thread_info
   /* The handle to the thread.  */
   HANDLE h;
 
+  /* Thread Information Block address.  */
+  CORE_ADDR thread_local_base;
+
   /* Non zero if SuspendThread was called on this thread.  */
   int suspended;
 


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