* python/py-progspace.c (py_free_pspace): Obtain arch another
[deliverable/binutils-gdb.git] / gdb / windows-nat.c
index 67f0c99599a9779bfa5a5c5c33498adf76bba81d..a1c991099fdcc7e3e34c3d4efd26f5d4e9c5c888 100644 (file)
@@ -1,7 +1,7 @@
 /* Target-vector operations for controlling windows child processes, for GDB.
 
    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+   2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
    Contributed by Cygnus Solutions, A Red Hat Company.
 
 #include <stdlib.h>
 #include <windows.h>
 #include <imagehlp.h>
+#include <psapi.h>
 #ifdef __CYGWIN__
 #include <sys/cygwin.h>
+#include <cygwin/version.h>
 #endif
 #include <signal.h>
 
 
 #include "windows-tdep.h"
 #include "windows-nat.h"
+#include "i386-nat.h"
+#include "complaints.h"
+
+#define AdjustTokenPrivileges          dyn_AdjustTokenPrivileges
+#define DebugActiveProcessStop         dyn_DebugActiveProcessStop
+#define DebugBreakProcess              dyn_DebugBreakProcess
+#define DebugSetProcessKillOnExit      dyn_DebugSetProcessKillOnExit
+#define EnumProcessModules             dyn_EnumProcessModules
+#define GetModuleInformation           dyn_GetModuleInformation
+#define LookupPrivilegeValueA          dyn_LookupPrivilegeValueA
+#define OpenProcessToken               dyn_OpenProcessToken
+#define GetConsoleFontSize             dyn_GetConsoleFontSize
+#define GetCurrentConsoleFont          dyn_GetCurrentConsoleFont
+
+static BOOL WINAPI (*AdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES,
+                                           DWORD, PTOKEN_PRIVILEGES, PDWORD);
+static BOOL WINAPI (*DebugActiveProcessStop) (DWORD);
+static BOOL WINAPI (*DebugBreakProcess) (HANDLE);
+static BOOL WINAPI (*DebugSetProcessKillOnExit) (BOOL);
+static BOOL WINAPI (*EnumProcessModules) (HANDLE, HMODULE *, DWORD,
+                                         LPDWORD);
+static BOOL WINAPI (*GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO,
+                                           DWORD);
+static BOOL WINAPI (*LookupPrivilegeValueA)(LPCSTR, LPCSTR, PLUID);
+static BOOL WINAPI (*OpenProcessToken)(HANDLE, DWORD, PHANDLE);
+static BOOL WINAPI (*GetCurrentConsoleFont) (HANDLE, BOOL, CONSOLE_FONT_INFO *);
+static COORD WINAPI (*GetConsoleFontSize) (HANDLE, DWORD);
 
 static struct target_ops windows_ops;
 
-#ifdef __CYGWIN__
+#undef STARTUPINFO
+#undef CreateProcess
+#undef GetModuleFileNameEx
+
+#ifndef __CYGWIN__
+# define __PMAX        (MAX_PATH + 1)
+  static DWORD WINAPI (*GetModuleFileNameEx) (HANDLE, HMODULE, LPSTR, DWORD);
+# define STARTUPINFO STARTUPINFOA
+# define CreateProcess CreateProcessA
+# define GetModuleFileNameEx_name "GetModuleFileNameExA"
+# define bad_GetModuleFileNameEx bad_GetModuleFileNameExA
+#else
+# define __PMAX        PATH_MAX
 /* The starting and ending address of the cygwin1.dll text segment. */
-static CORE_ADDR cygwin_load_start;
-static CORE_ADDR cygwin_load_end;
+  static CORE_ADDR cygwin_load_start;
+  static CORE_ADDR cygwin_load_end;
+# if CYGWIN_VERSION_DLL_MAKE_COMBINED(CYGWIN_VERSION_API_MAJOR,CYGWIN_VERSION_API_MINOR) >= 181
+#   define __USEWIDE
+    typedef wchar_t cygwin_buf_t;
+    static DWORD WINAPI (*GetModuleFileNameEx) (HANDLE, HMODULE, LPWSTR, DWORD);
+#   define STARTUPINFO STARTUPINFOW
+#   define CreateProcess CreateProcessW
+#   define GetModuleFileNameEx_name "GetModuleFileNameExW"
+#   define bad_GetModuleFileNameEx bad_GetModuleFileNameExW
+# else
+#   define CCP_POSIX_TO_WIN_W 1
+#   define CCP_WIN_W_TO_POSIX 3
+#   define cygwin_conv_path(op, from, to, size)  \
+         (op == CCP_WIN_W_TO_POSIX) ? \
+         cygwin_conv_to_full_posix_path (from, to) : \
+         cygwin_conv_to_win32_path (from, to)
+    typedef char cygwin_buf_t;
+    static DWORD WINAPI (*GetModuleFileNameEx) (HANDLE, HMODULE, LPSTR, DWORD);
+#   define STARTUPINFO STARTUPINFOA
+#   define CreateProcess CreateProcessA
+#   define GetModuleFileNameEx_name "GetModuleFileNameExA"
+#   define bad_GetModuleFileNameEx bad_GetModuleFileNameExA
+#   define CW_SET_DOS_FILE_WARNING -1  /* no-op this for older Cygwin */
+# endif
 #endif
 
 static int have_saved_context; /* True if we've saved context from a cygwin signal. */
@@ -84,7 +148,6 @@ enum
     CONTEXT_DEBUGGER = (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
   };
 #endif
-#include <psapi.h>
 
 #ifndef CONTEXT_EXTENDED_REGISTERS
 /* This macro is only defined on ia32.  It only makes sense on this target,
@@ -95,9 +158,11 @@ enum
 #define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_DEBUG_REGISTERS \
        | CONTEXT_EXTENDED_REGISTERS
 
-static unsigned dr[8];
+static uintptr_t dr[8];
 static int debug_registers_changed;
 static int debug_registers_used;
+
+static int windows_initialization_done;
 #define DR6_CLEAR_VALUE 0xffff0ff0
 
 /* The string sent by cygwin when it processes a signal.
@@ -114,7 +179,11 @@ 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 (void);
+static void windows_kill_inferior (struct target_ops *);
+
+static void cygwin_set_dr (int i, CORE_ADDR addr);
+static void cygwin_set_dr7 (unsigned long val);
+static unsigned long cygwin_get_dr6 (void);
 
 static enum target_signal last_sig = TARGET_SIGNAL_0;
 /* Set if a signal was received from the debugged process */
@@ -126,6 +195,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;
@@ -255,7 +325,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;
@@ -270,6 +340,7 @@ windows_add_thread (ptid_t ptid, HANDLE h)
   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);
@@ -366,7 +437,7 @@ do_windows_fetch_inferior_registers (struct regcache *regcache, int r)
          thread_info *th = current_thread;
          th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
          GetThreadContext (th->h, &th->context);
-         /* Copy dr values from that thread. 
+         /* Copy dr values from that thread.
             But only if there were not modified since last stop. PR gdb/2388 */
          if (!debug_registers_changed)
            {
@@ -438,14 +509,6 @@ windows_store_inferior_registers (struct target_ops *ops,
     do_windows_store_inferior_registers (regcache, r);
 }
 
-static int psapi_loaded = 0;
-static BOOL WINAPI (*psapi_EnumProcessModules) (HANDLE, HMODULE *, DWORD,
-                                               LPDWORD);
-static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO,
-                                                 DWORD);
-static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR,
-                                                  DWORD);
-
 /* Get the name of a given module at at given base address.  If base_address
    is zero return the first loaded module (which is always the name of the
    executable).  */
@@ -459,21 +522,16 @@ get_module_name (LPVOID base_address, char *dll_name_ret)
   HMODULE *DllHandle = dh_buf; /* Set to temporary storage for initial query */
   DWORD cbNeeded;
 #ifdef __CYGWIN__
-  char pathbuf[PATH_MAX + 1];  /* Temporary storage prior to converting to
-                                  posix form */
-#else
-  char *pathbuf = dll_name_ret;        /* Just copy directly to passed-in arg */
+  cygwin_buf_t pathbuf[__PMAX];        /* Temporary storage prior to converting to
+                                  posix form.  __PMAX is always enough
+                                  as long as SO_NAME_MAX_PATH_SIZE is defined
+                                  as 512. */
 #endif
 
-  /* If psapi_loaded < 0 either psapi.dll is not available or it does not contain
-     the needed functions. */
-  if (psapi_loaded <= 0)
-    goto failed;
-
   cbNeeded = 0;
   /* Find size of buffer needed to handle list of modules loaded in inferior */
-  if (!psapi_EnumProcessModules (current_process_handle, DllHandle,
-                                sizeof (HMODULE), &cbNeeded) || !cbNeeded)
+  if (!EnumProcessModules (current_process_handle, DllHandle,
+                          sizeof (HMODULE), &cbNeeded) || !cbNeeded)
     goto failed;
 
   /* Allocate correct amount of space for module list */
@@ -482,27 +540,34 @@ get_module_name (LPVOID base_address, char *dll_name_ret)
     goto failed;
 
   /* Get the list of modules */
-  if (!psapi_EnumProcessModules (current_process_handle, DllHandle, cbNeeded,
+  if (!EnumProcessModules (current_process_handle, DllHandle, cbNeeded,
                                 &cbNeeded))
     goto failed;
 
   for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
     {
       /* Get information on this module */
-      if (!psapi_GetModuleInformation (current_process_handle, DllHandle[i],
-                                      &mi, sizeof (mi)))
+      if (!GetModuleInformation (current_process_handle, DllHandle[i],
+                                &mi, sizeof (mi)))
        error (_("Can't get module info"));
 
       if (!base_address || mi.lpBaseOfDll == base_address)
        {
          /* Try to find the name of the given module */
-         len = psapi_GetModuleFileNameExA (current_process_handle,
-                                           DllHandle[i], pathbuf, MAX_PATH);
-         if (len == 0)
-           error (_("Error getting dll name: %u."), (unsigned) GetLastError ());
 #ifdef __CYGWIN__
          /* Cygwin prefers that the path be in /x/y/z format */
-         cygwin_conv_to_full_posix_path (pathbuf, dll_name_ret);
+         len = GetModuleFileNameEx (current_process_handle,
+                                     DllHandle[i], pathbuf, __PMAX);
+         if (len == 0)
+           error (_("Error getting dll name: %lu."), GetLastError ());
+         if (cygwin_conv_path (CCP_WIN_W_TO_POSIX, pathbuf, dll_name_ret,
+                               __PMAX) < 0)
+           error (_("Error converting dll name to POSIX: %d."), errno);
+#else
+         len = GetModuleFileNameEx (current_process_handle,
+                                     DllHandle[i], dll_name_ret, __PMAX);
+         if (len == 0)
+           error (_("Error getting dll name: %u."), (unsigned) GetLastError ());
 #endif
          return 1;     /* success */
        }
@@ -540,7 +605,9 @@ static int
 safe_symbol_file_add_stub (void *argv)
 {
 #define p ((struct safe_symbol_file_add_args *) argv)
-  p->ret = symbol_file_add (p->name, p->from_tty, p->addrs, p->mainline, p->flags);
+  const int add_flags = ((p->from_tty ? SYMFILE_VERBOSE : 0)
+                         | (p->mainline ? SYMFILE_MAINLINE : 0));
+  p->ret = symbol_file_add (p->name, add_flags, p->addrs, p->flags);
   return !!p->ret;
 #undef p
 }
@@ -591,12 +658,12 @@ static struct so_list *
 windows_make_so (const char *name, LPVOID load_addr)
 {
   struct so_list *so;
-  char buf[MAX_PATH + 1];
-  char cwd[MAX_PATH + 1];
   char *p;
+#ifndef __CYGWIN__
+  char buf[__PMAX];
+  char cwd[__PMAX];
   WIN32_FIND_DATA w32_fd;
   HANDLE h = FindFirstFile(name, &w32_fd);
-  MEMORY_BASIC_INFORMATION m;
 
   if (h == INVALID_HANDLE_VALUE)
     strcpy (buf, name);
@@ -614,12 +681,31 @@ windows_make_so (const char *name, LPVOID load_addr)
          SetCurrentDirectory (cwd);
        }
     }
-
   if (strcasecmp (buf, "ntdll.dll") == 0)
     {
       GetSystemDirectory (buf, sizeof (buf));
       strcat (buf, "\\ntdll.dll");
     }
+#else
+  cygwin_buf_t buf[__PMAX];
+
+  buf[0] = 0;
+  if (access (name, F_OK) != 0)
+    {
+      if (strcasecmp (name, "ntdll.dll") == 0)
+#ifdef __USEWIDE
+       {
+         GetSystemDirectoryW (buf, sizeof (buf) / sizeof (wchar_t));
+         wcscat (buf, L"\\ntdll.dll");
+       }
+#else
+       {
+         GetSystemDirectoryA (buf, sizeof (buf) / sizeof (wchar_t));
+         strcat (buf, "\\ntdll.dll");
+       }
+#endif
+    }
+#endif
   so = XZALLOC (struct so_list);
   so->lm_info = (struct lm_info *) xmalloc (sizeof (struct lm_info));
   so->lm_info->load_addr = load_addr;
@@ -627,7 +713,20 @@ windows_make_so (const char *name, LPVOID load_addr)
 #ifndef __CYGWIN__
   strcpy (so->so_name, buf);
 #else
-  cygwin_conv_to_posix_path (buf, so->so_name);
+  if (buf[0])
+    cygwin_conv_path (CCP_WIN_W_TO_POSIX, buf, so->so_name,
+                     SO_NAME_MAX_PATH_SIZE);
+  else
+    {
+      char *rname = realpath (name, NULL);
+      if (rname && strlen (rname) < SO_NAME_MAX_PATH_SIZE)
+       {
+         strcpy (so->so_name, rname);
+         free (rname);
+       }
+      else
+       error (_("dll path too long"));
+    }
   /* Record cygwin1.dll .text start/end.  */
   p = strchr (so->so_name, '\0') - (sizeof ("/cygwin1.dll") - 1);
   if (p >= so->so_name && strcasecmp (p, "/cygwin1.dll") == 0)
@@ -666,7 +765,11 @@ windows_make_so (const char *name, LPVOID load_addr)
 static char *
 get_image_name (HANDLE h, void *address, int unicode)
 {
-  static char buf[(2 * MAX_PATH) + 1];
+#ifdef __CYGWIN__
+  static char buf[__PMAX];
+#else
+  static char buf[(2 * __PMAX) + 1];
+#endif
   DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
   char *address_ptr;
   int len = 0;
@@ -697,8 +800,12 @@ get_image_name (HANDLE h, void *address, int unicode)
       WCHAR *unicode_address = (WCHAR *) alloca (len * sizeof (WCHAR));
       ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR),
                         &done);
-
-      WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, len, 0, 0);
+#ifdef __CYGWIN__
+      wcstombs (buf, unicode_address, __PMAX);
+#else
+      WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, sizeof buf,
+                          0, 0);
+#endif
     }
 
   return buf;
@@ -710,7 +817,7 @@ static int
 handle_load_dll (void *dummy)
 {
   LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
-  char dll_buf[MAX_PATH + 1];
+  char dll_buf[__PMAX];
   char *dll_name = NULL;
 
   dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
@@ -729,8 +836,8 @@ handle_load_dll (void *dummy)
   solib_end->next = windows_make_so (dll_name, event->lpBaseOfDll);
   solib_end = solib_end->next;
 
-  DEBUG_EVENTS (("gdb: Loading dll \"%s\" at %p.\n", solib_end->so_name,
-                solib_end->lm_info->load_addr));
+  DEBUG_EVENTS (("gdb: Loading dll \"%s\" at %s.\n", solib_end->so_name,
+                host_address_to_string (solib_end->lm_info->load_addr)));
 
   return 1;
 }
@@ -763,7 +870,15 @@ handle_unload_dll (void *dummy)
        return 1;
       }
 
-  error (_("Error: dll starting at %p not found."), lpBaseOfDll);
+  /* We did not find any DLL that was previously loaded at this address,
+     so register a complaint.  We do not report an error, because we have
+     observed that this may be happening under some circumstances.  For
+     instance, running 32bit applications on x64 Windows causes us to receive
+     4 mysterious UNLOAD_DLL_DEBUG_EVENTs during the startup phase (these
+     events are apparently caused by the WOW layer, the interface between
+     32bit and 64bit worlds).  */
+  complaint (&symfile_complaints, _("dll starting at %s not found."),
+            host_address_to_string (lpBaseOfDll));
 
   return 0;
 }
@@ -921,7 +1036,11 @@ display_selector (HANDLE thread, DWORD sel)
     }
   else
     {
-      printf_filtered ("Invalid selector 0x%lx.\n",sel);
+      DWORD err = GetLastError ();
+      if (err == ERROR_NOT_SUPPORTED)
+       printf_filtered ("Function not supported\n");
+      else
+       printf_filtered ("Invalid selector 0x%lx.\n",sel);
       return 0;
     }
 }
@@ -965,18 +1084,10 @@ display_selectors (char * args, int from_tty)
     }
 }
 
-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 %p\n", x, \
-          current_event.u.Exception.ExceptionRecord.ExceptionAddress)
+  printf_unfiltered ("gdb: Target exception %s at %s\n", x, \
+    host_address_to_string (\
+      current_event.u.Exception.ExceptionRecord.ExceptionAddress))
 
 static int
 handle_exception (struct target_waitstatus *ourstatus)
@@ -1087,9 +1198,10 @@ handle_exception (struct target_waitstatus *ourstatus)
       /* Treat unhandled first chance exceptions specially. */
       if (current_event.u.Exception.dwFirstChance)
        return -1;
-      printf_unfiltered ("gdb: unknown target exception 0x%08lx at %p\n",
-                   current_event.u.Exception.ExceptionRecord.ExceptionCode,
-               current_event.u.Exception.ExceptionRecord.ExceptionAddress);
+      printf_unfiltered ("gdb: unknown target exception 0x%08lx at %s\n",
+       current_event.u.Exception.ExceptionRecord.ExceptionCode,
+       host_address_to_string (
+         current_event.u.Exception.ExceptionRecord.ExceptionAddress));
       ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
       break;
     }
@@ -1107,7 +1219,7 @@ windows_continue (DWORD continue_status, int id)
   thread_info *th;
   BOOL res;
 
-  DEBUG_EVENTS (("ContinueDebugEvent (cpid=%ld, ctid=%ld, %s);\n",
+  DEBUG_EVENTS (("ContinueDebugEvent (cpid=%ld, ctid=%lx, %s);\n",
                  current_event.dwProcessId, current_event.dwThreadId,
                  continue_status == DBG_CONTINUE ?
                  "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED"));
@@ -1160,9 +1272,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;
 }
 
@@ -1227,9 +1341,10 @@ windows_resume (struct target_ops *ops,
       if (step)
        {
          /* Single step by setting t bit */
-         windows_fetch_inferior_registers (ops,
-                                           get_current_regcache (),
-                                           gdbarch_ps_regnum (current_gdbarch));
+         struct regcache *regcache = get_current_regcache ();
+         struct gdbarch *gdbarch = get_regcache_arch (regcache);
+         windows_fetch_inferior_registers (ops, regcache,
+                                           gdbarch_ps_regnum (gdbarch));
          th->context.EFlags |= FLAG_TRACE_BIT;
        }
 
@@ -1258,9 +1373,34 @@ windows_resume (struct target_ops *ops,
     windows_continue (continue_status, ptid_get_tid (ptid));
 }
 
+/* Ctrl-C handler used when the inferior is not run in the same console.  The
+   handler is in charge of interrupting the inferior using DebugBreakProcess.
+   Note that this function is not available prior to Windows XP.  In this case
+   we emit a warning.  */
+BOOL WINAPI
+ctrl_c_handler (DWORD event_type)
+{
+  const int attach_flag = current_inferior ()->attach_flag;
+
+  /* Only handle Ctrl-C and Ctrl-Break events.  Ignore others.  */
+  if (event_type != CTRL_C_EVENT && event_type != CTRL_BREAK_EVENT)
+    return FALSE;
+
+  /* If the inferior and the debugger share the same console, do nothing as
+     the inferior has also received the Ctrl-C event.  */
+  if (!new_console && !attach_flag)
+    return TRUE;
+
+  if (!DebugBreakProcess (current_process_handle))
+    warning (_("\
+Could not interrupt program.  Press Ctrl-c in the program console."));
+
+  /* Return true to tell that Ctrl-C has been handled.  */
+  return TRUE;
+}
+
 /* Get the next event from the child.  Return 1 if the event requires
-   handling by WFI (or whatever).
- */
+   handling by WFI (or whatever).  */
 static int
 get_windows_debug_event (struct target_ops *ops,
                         int pid, struct target_waitstatus *ourstatus)
@@ -1310,14 +1450,17 @@ get_windows_debug_event (struct target_ops *ops,
       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:
-      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
+      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
                     (unsigned) current_event.dwProcessId,
                     (unsigned) current_event.dwThreadId,
                     "EXIT_THREAD_DEBUG_EVENT"));
+
       if (current_event.dwThreadId != main_thread_id)
        {
          windows_delete_thread (ptid_build (current_event.dwProcessId, 0,
@@ -1327,7 +1470,7 @@ get_windows_debug_event (struct target_ops *ops,
       break;
 
     case CREATE_PROCESS_DEBUG_EVENT:
-      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
+      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
                     (unsigned) current_event.dwProcessId,
                     (unsigned) current_event.dwThreadId,
                     "CREATE_PROCESS_DEBUG_EVENT"));
@@ -1337,30 +1480,39 @@ get_windows_debug_event (struct target_ops *ops,
 
       current_process_handle = current_event.u.CreateProcessInfo.hProcess;
       if (main_thread_id)
-       windows_delete_thread (ptid_build (current_event.dwProcessId, 0,
-                                        main_thread_id));
+       windows_delete_thread (ptid_build (current_event.dwProcessId, 0,
+                                          main_thread_id));
       main_thread_id = current_event.dwThreadId;
       /* Add the main thread */
       th = windows_add_thread (ptid_build (current_event.dwProcessId, 0,
-                                        current_event.dwThreadId),
-                            current_event.u.CreateProcessInfo.hThread);
+                                          current_event.dwThreadId),
+            current_event.u.CreateProcessInfo.hThread,
+            current_event.u.CreateProcessInfo.lpThreadLocalBase);
       retval = current_event.dwThreadId;
       break;
 
     case EXIT_PROCESS_DEBUG_EVENT:
-      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
+      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
                     (unsigned) current_event.dwProcessId,
                     (unsigned) current_event.dwThreadId,
                     "EXIT_PROCESS_DEBUG_EVENT"));
-      if (saw_create != 1)
-       break;
-      ourstatus->kind = TARGET_WAITKIND_EXITED;
-      ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
-      retval = main_thread_id;
+      if (!windows_initialization_done)
+       {
+         target_terminal_ours ();
+         target_mourn_inferior ();
+         error (_("During startup program exited with code 0x%x."),
+                (unsigned int) current_event.u.ExitProcess.dwExitCode);
+       }
+      else if (saw_create == 1)
+       {
+         ourstatus->kind = TARGET_WAITKIND_EXITED;
+         ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
+         retval = main_thread_id;
+       }
       break;
 
     case LOAD_DLL_DEBUG_EVENT:
-      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
+      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
                     (unsigned) current_event.dwProcessId,
                     (unsigned) current_event.dwThreadId,
                     "LOAD_DLL_DEBUG_EVENT"));
@@ -1374,7 +1526,7 @@ get_windows_debug_event (struct target_ops *ops,
       break;
 
     case UNLOAD_DLL_DEBUG_EVENT:
-      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
+      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
                     (unsigned) current_event.dwProcessId,
                     (unsigned) current_event.dwThreadId,
                     "UNLOAD_DLL_DEBUG_EVENT"));
@@ -1387,7 +1539,7 @@ get_windows_debug_event (struct target_ops *ops,
       break;
 
     case EXCEPTION_DEBUG_EVENT:
-      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
+      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
                     (unsigned) current_event.dwProcessId,
                     (unsigned) current_event.dwThreadId,
                     "EXCEPTION_DEBUG_EVENT"));
@@ -1409,7 +1561,7 @@ get_windows_debug_event (struct target_ops *ops,
       break;
 
     case OUTPUT_DEBUG_STRING_EVENT:    /* message from the kernel */
-      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
+      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
                     (unsigned) current_event.dwProcessId,
                     (unsigned) current_event.dwThreadId,
                     "OUTPUT_DEBUG_STRING_EVENT"));
@@ -1450,7 +1602,7 @@ out:
 /* Wait for interesting events to occur in the target process.  */
 static ptid_t
 windows_wait (struct target_ops *ops,
-             ptid_t ptid, struct target_waitstatus *ourstatus)
+             ptid_t ptid, struct target_waitstatus *ourstatus, int options)
 {
   int pid = -1;
 
@@ -1465,23 +1617,36 @@ windows_wait (struct target_ops *ops,
   while (1)
     {
       int retval;
-      
-      /* Ignore CTRL+C signals while waiting for a debug event.
-         FIXME: brobecker/2008-05-20: When the user presses CTRL+C while
-         the inferior is running, both the inferior and GDB receive the
-         associated signal.  If the inferior receives the signal first
-         and the delay until GDB receives that signal is sufficiently long,
-         GDB can sometimes receive the SIGINT after we have unblocked
-         the CTRL+C handler.  This would lead to the debugger to stop
-         prematurely while handling the new-thread event that comes
-         with the handling of the SIGINT inside the inferior, and then
-         stop again immediately when the user tries to resume the execution
-         in the inferior.  This is a classic race, and it would be nice
-         to find a better solution to that problem.  But in the meantime,
-         the current approach already greatly mitigate this issue.  */
-      SetConsoleCtrlHandler (NULL, TRUE);
+
+      /* If the user presses Ctrl-c while the debugger is waiting
+        for an event, he expects the debugger to interrupt his program
+        and to get the prompt back.  There are two possible situations:
+
+          - The debugger and the program do not share the console, in
+            which case the Ctrl-c event only reached the debugger.
+            In that case, the ctrl_c handler will take care of interrupting
+            the inferior. Note that this case is working starting with
+            Windows XP. For Windows 2000, Ctrl-C should be pressed in the
+            inferior console.
+
+          - The debugger and the program share the same console, in which
+            case both debugger and inferior will receive the Ctrl-c event.
+            In that case the ctrl_c handler will ignore the event, as the
+            Ctrl-c event generated inside the inferior will trigger the
+            expected debug event.
+
+            FIXME: brobecker/2008-05-20: If the inferior receives the
+            signal first and the delay until GDB receives that signal
+            is sufficiently long, GDB can sometimes receive the SIGINT
+            after we have unblocked the CTRL+C handler.  This would
+            lead to the debugger stopping prematurely while handling
+            the new-thread event that comes with the handling of the SIGINT
+            inside the inferior, and then stop again immediately when
+            the user tries to resume the execution in the inferior.
+            This is a classic race that we should try to fix one day.  */
+      SetConsoleCtrlHandler (&ctrl_c_handler, TRUE);
       retval = get_windows_debug_event (ops, pid, ourstatus);
-      SetConsoleCtrlHandler (NULL, FALSE);
+      SetConsoleCtrlHandler (&ctrl_c_handler, FALSE);
 
       if (retval)
        return ptid_build (current_event.dwProcessId, 0, retval);
@@ -1493,7 +1658,7 @@ windows_wait (struct target_ops *ops,
            detach = deprecated_ui_loop_hook (0);
 
          if (detach)
-           windows_kill_inferior ();
+           windows_kill_inferior (ops);
        }
     }
 }
@@ -1525,7 +1690,8 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
   clear_proceed_status ();
   init_wait_for_inferior ();
 
-  inf = add_inferior (pid);
+  inf = current_inferior ();
+  inferior_appeared (inf, pid);
   inf->attach_flag = attaching;
 
   /* Make the new process the current inferior, so terminal handling
@@ -1537,53 +1703,25 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
   terminal_init_inferior_with_pgrp (pid);
   target_terminal_inferior ();
 
-  inf->stop_soon = STOP_QUIETLY;
+  windows_initialization_done = 0;
+  inf->control.stop_soon = STOP_QUIETLY;
   while (1)
     {
       stop_after_trap = 1;
       wait_for_inferior (0);
       tp = inferior_thread ();
-      if (tp->stop_signal != TARGET_SIGNAL_TRAP)
-       resume (0, tp->stop_signal);
+      if (tp->suspend.stop_signal != TARGET_SIGNAL_TRAP)
+       resume (0, tp->suspend.stop_signal);
       else
        break;
     }
 
-  inf->stop_soon = NO_STOP_QUIETLY;
+  windows_initialization_done = 1;
+  inf->control.stop_soon = NO_STOP_QUIETLY;
   stop_after_trap = 0;
   return;
 }
 
-/* Since Windows XP, detaching from a process is supported by Windows.
-   The following code tries loading the appropriate functions dynamically.
-   If loading these functions succeeds use them to actually detach from
-   the inferior process, otherwise behave as usual, pretending that
-   detach has worked. */
-static BOOL WINAPI (*kernel32_DebugSetProcessKillOnExit)(BOOL);
-static BOOL WINAPI (*kernel32_DebugActiveProcessStop)(DWORD);
-
-static int
-has_detach_ability (void)
-{
-  static HMODULE kernel32 = NULL;
-
-  if (!kernel32)
-    kernel32 = LoadLibrary ("kernel32.dll");
-  if (kernel32)
-    {
-      if (!kernel32_DebugSetProcessKillOnExit)
-       kernel32_DebugSetProcessKillOnExit =
-         (void *) GetProcAddress (kernel32, "DebugSetProcessKillOnExit");
-      if (!kernel32_DebugActiveProcessStop)
-       kernel32_DebugActiveProcessStop =
-         (void *) GetProcAddress (kernel32, "DebugActiveProcessStop");
-      if (kernel32_DebugSetProcessKillOnExit
-         && kernel32_DebugActiveProcessStop)
-       return 1;
-    }
-  return 0;
-}
-
 /* Try to set or remove a user privilege to the current process.  Return -1
    if that fails, the previous setting of that privilege otherwise.
 
@@ -1593,47 +1731,18 @@ has_detach_ability (void)
 static int
 set_process_privilege (const char *privilege, BOOL enable)
 {
-  static HMODULE advapi32 = NULL;
-  static BOOL WINAPI (*OpenProcessToken)(HANDLE, DWORD, PHANDLE);
-  static BOOL WINAPI (*LookupPrivilegeValue)(LPCSTR, LPCSTR, PLUID);
-  static BOOL WINAPI (*AdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES,
-                                             DWORD, PTOKEN_PRIVILEGES, PDWORD);
-
   HANDLE token_hdl = NULL;
   LUID restore_priv;
   TOKEN_PRIVILEGES new_priv, orig_priv;
   int ret = -1;
   DWORD size;
 
-  if (GetVersion () >= 0x80000000)  /* No security availbale on 9x/Me */
-    return 0;
-
-  if (!advapi32)
-    {
-      if (!(advapi32 = LoadLibrary ("advapi32.dll")))
-       goto out;
-      if (!OpenProcessToken)
-       OpenProcessToken =
-          (void *) GetProcAddress (advapi32, "OpenProcessToken");
-      if (!LookupPrivilegeValue)
-       LookupPrivilegeValue =
-          (void *) GetProcAddress (advapi32, "LookupPrivilegeValueA");
-      if (!AdjustTokenPrivileges)
-       AdjustTokenPrivileges =
-          (void *) GetProcAddress (advapi32, "AdjustTokenPrivileges");
-      if (!OpenProcessToken || !LookupPrivilegeValue || !AdjustTokenPrivileges)
-       {
-         advapi32 = NULL;
-         goto out;
-       }
-    }
-
   if (!OpenProcessToken (GetCurrentProcess (),
                         TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
                         &token_hdl))
     goto out;
 
-  if (!LookupPrivilegeValue (NULL, privilege, &restore_priv))
+  if (!LookupPrivilegeValueA (NULL, privilege, &restore_priv))
     goto out;
 
   new_priv.PrivilegeCount = 1;
@@ -1669,8 +1778,7 @@ windows_attach (struct target_ops *ops, char *args, int from_tty)
   BOOL ok;
   DWORD pid;
 
-  if (!args)
-    error_no_arg (_("process-id to attach"));
+  pid = parse_pid_to_attach (args);
 
   if (set_process_privilege (SE_DEBUG_NAME, TRUE) < 0)
     {
@@ -1678,8 +1786,6 @@ windows_attach (struct target_ops *ops, char *args, int from_tty)
       printf_unfiltered ("This can cause attach to fail on Windows NT/2K/XP\n");
     }
 
-  pid = strtoul (args, 0, 0);          /* Windows pid */
-
   windows_init_thread_list ();
   ok = DebugActiveProcess (pid);
   saw_create = 0;
@@ -1698,8 +1804,7 @@ windows_attach (struct target_ops *ops, char *args, int from_tty)
   if (!ok)
     error (_("Can't attach to process."));
 
-  if (has_detach_ability ())
-    kernel32_DebugSetProcessKillOnExit (FALSE);
+  DebugSetProcessKillOnExit (FALSE);
 
   if (from_tty)
     {
@@ -1724,19 +1829,17 @@ windows_detach (struct target_ops *ops, char *args, int from_tty)
 {
   int detached = 1;
 
-  if (has_detach_ability ())
-    {
-      ptid_t ptid = {-1};
-      windows_resume (ops, ptid, 0, TARGET_SIGNAL_0);
+  ptid_t ptid = {-1};
+  windows_resume (ops, ptid, 0, TARGET_SIGNAL_0);
 
-      if (!kernel32_DebugActiveProcessStop (current_event.dwProcessId))
-       {
-         error (_("Can't detach process %lu (error %lu)"),
-                current_event.dwProcessId, GetLastError ());
-         detached = 0;
-       }
-      kernel32_DebugSetProcessKillOnExit (FALSE);
+  if (!DebugActiveProcessStop (current_event.dwProcessId))
+    {
+      error (_("Can't detach process %lu (error %lu)"),
+            current_event.dwProcessId, GetLastError ());
+      detached = 0;
     }
+  DebugSetProcessKillOnExit (FALSE);
+
   if (detached && from_tty)
     {
       char *exec_file = get_exec_file (0);
@@ -1756,8 +1859,7 @@ windows_detach (struct target_ops *ops, char *args, int from_tty)
 static char *
 windows_pid_to_exec_file (int pid)
 {
-  static char path[MAX_PATH + 1];
-
+  static char path[__PMAX];
 #ifdef __CYGWIN__
   /* Try to find exe name as symlink target of /proc/<pid>/exe */
   int nchars;
@@ -1797,6 +1899,51 @@ windows_open (char *arg, int from_tty)
   error (_("Use the \"run\" command to start a Unix child process."));
 }
 
+/* Modify CreateProcess parameters for use of a new separate console.
+   Parameters are:
+   *FLAGS: DWORD parameter for general process creation flags.
+   *SI: STARTUPINFO structure, for which the console window size and
+   console buffer size is filled in if GDB is running in a console.
+   to create the new console.
+   The size of the used font is not available on all versions of
+   Windows OS.  Furthermore, the current font might not be the default
+   font, but this is still better than before.
+   If the windows and buffer sizes are computed,
+   SI->DWFLAGS is changed so that this information is used
+   by CreateProcess function.  */
+
+static void
+windows_set_console_info (STARTUPINFO *si, DWORD *flags)
+{
+  HANDLE hconsole = CreateFile ("CONOUT$", GENERIC_READ | GENERIC_WRITE,
+                               FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+
+  if (hconsole != INVALID_HANDLE_VALUE)
+    {
+      CONSOLE_SCREEN_BUFFER_INFO sbinfo;
+      COORD font_size;
+      CONSOLE_FONT_INFO cfi;
+
+      GetCurrentConsoleFont (hconsole, FALSE, &cfi);
+      font_size = GetConsoleFontSize (hconsole, cfi.nFont);
+      GetConsoleScreenBufferInfo(hconsole, &sbinfo);
+      si->dwXSize = sbinfo.srWindow.Right - sbinfo.srWindow.Left + 1;
+      si->dwYSize = sbinfo.srWindow.Bottom - sbinfo.srWindow.Top + 1;
+      if (font_size.X)
+       si->dwXSize *= font_size.X;
+      else
+       si->dwXSize *= 8;
+      if (font_size.Y)
+       si->dwYSize *= font_size.Y;
+      else
+       si->dwYSize *= 12;
+      si->dwXCountChars = sbinfo.dwSize.X;
+      si->dwYCountChars = sbinfo.dwSize.Y;
+      si->dwFlags |= STARTF_USESIZE | STARTF_USECOUNTCHARS;
+    }
+  *flags |= CREATE_NEW_CONSOLE;
+}
+
 /* Start an inferior windows child process and sets inferior_ptid to its pid.
    EXEC_FILE is the file to run.
    ALLARGS is a string containing the arguments to the program.
@@ -1807,16 +1954,26 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
                       char *allargs, char **in_env, int from_tty)
 {
   STARTUPINFO si;
-  PROCESS_INFORMATION pi;
-  BOOL ret;
-  DWORD flags;
-  char *args;
-  char real_path[MAXPATHLEN];
-  char *toexec;
-  char shell[MAX_PATH + 1]; /* Path to shell */
+#ifdef __CYGWIN__
+  cygwin_buf_t real_path[__PMAX];
+  cygwin_buf_t shell[__PMAX]; /* Path to shell */
   const char *sh;
+  cygwin_buf_t *toexec;
+  cygwin_buf_t *cygallargs;
+  cygwin_buf_t *args;
+  size_t len;
   int tty;
   int ostdin, ostdout, ostderr;
+#else
+  char real_path[__PMAX];
+  char shell[__PMAX]; /* Path to shell */
+  char *toexec;
+  char *args;
+  HANDLE tty;
+#endif
+  PROCESS_INFORMATION pi;
+  BOOL ret;
+  DWORD flags = 0;
   const char *inferior_io_terminal = get_inferior_io_terminal ();
 
   if (!exec_file)
@@ -1825,44 +1982,64 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
   memset (&si, 0, sizeof (si));
   si.cb = sizeof (si);
 
+  if (new_group)
+    flags |= CREATE_NEW_PROCESS_GROUP;
+
+  if (new_console)
+    windows_set_console_info (&si, &flags);
+
 #ifdef __CYGWIN__
   if (!useshell)
     {
-      flags = DEBUG_ONLY_THIS_PROCESS;
-      cygwin_conv_to_win32_path (exec_file, real_path);
+      flags |= DEBUG_ONLY_THIS_PROCESS;
+      if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, exec_file, real_path,
+                           __PMAX * sizeof (cygwin_buf_t)) < 0)
+       error (_("Error starting executable: %d"), errno);
       toexec = real_path;
+#ifdef __USEWIDE
+      len = mbstowcs (NULL, allargs, 0) + 1;
+      if (len == (size_t) -1)
+       error (_("Error starting executable: %d"), errno);
+      cygallargs = (wchar_t *) alloca (len * sizeof (wchar_t));
+      mbstowcs (cygallargs, allargs, len);
+#else
+      cygallargs = allargs;
+#endif
     }
   else
     {
-      char *newallargs;
       sh = getenv ("SHELL");
       if (!sh)
        sh = "/bin/sh";
-      cygwin_conv_to_win32_path (sh, shell);
-      newallargs = alloca (sizeof (" -c 'exec  '") + strlen (exec_file)
-                          + strlen (allargs) + 2);
-      sprintf (newallargs, " -c 'exec %s %s'", exec_file, allargs);
-      allargs = newallargs;
-      toexec = shell;
-      flags = DEBUG_PROCESS;
-    }
+      if (cygwin_conv_path (CCP_POSIX_TO_WIN_W, sh, shell, __PMAX) < 0)
+       error (_("Error starting executable via shell: %d"), errno);
+#ifdef __USEWIDE
+      len = sizeof (L" -c 'exec  '") + mbstowcs (NULL, exec_file, 0)
+           + mbstowcs (NULL, allargs, 0) + 2;
+      cygallargs = (wchar_t *) alloca (len * sizeof (wchar_t));
+      swprintf (cygallargs, len, L" -c 'exec %s %s'", exec_file, allargs);
 #else
-  toexec = exec_file;
-  flags = DEBUG_ONLY_THIS_PROCESS;
+      cygallargs = (char *) alloca (sizeof (" -c 'exec  '") + strlen (exec_file)
+                                   + strlen (allargs) + 2);
+      sprintf (cygallargs, " -c 'exec %s %s'", exec_file, allargs);
 #endif
+      toexec = shell;
+      flags |= DEBUG_PROCESS;
+    }
 
-  if (new_group)
-    flags |= CREATE_NEW_PROCESS_GROUP;
-
-  if (new_console)
-    flags |= CREATE_NEW_CONSOLE;
-
-  args = alloca (strlen (toexec) + strlen (allargs) + 2);
+#ifdef __USEWIDE
+  args = (cygwin_buf_t *) alloca ((wcslen (toexec) + wcslen (cygallargs) + 2)
+                                 * sizeof (wchar_t));
+  wcscpy (args, toexec);
+  wcscat (args, L" ");
+  wcscat (args, cygallargs);
+#else
+  args = (cygwin_buf_t *) alloca (strlen (toexec) + strlen (cygallargs) + 2);
   strcpy (args, toexec);
   strcat (args, " ");
-  strcat (args, allargs);
+  strcat (args, cygallargs);
+#endif
 
-#ifdef __CYGWIN__
   /* Prepare the environment vars for CreateProcess.  */
   cygwin_internal (CW_SYNC_WINENV);
 
@@ -1886,7 +2063,6 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
          dup2 (tty, 2);
        }
     }
-#endif
 
   windows_init_thread_list ();
   ret = CreateProcess (0,
@@ -1899,8 +2075,6 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
                       NULL,    /* current directory */
                       &si,
                       &pi);
-
-#ifdef __CYGWIN__
   if (tty >= 0)
     {
       close (tty);
@@ -1911,6 +2085,50 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
       close (ostdout);
       close (ostderr);
     }
+#else
+  toexec = exec_file;
+  args = alloca (strlen (toexec) + strlen (allargs) + 2);
+  strcpy (args, toexec);
+  strcat (args, " ");
+  strcat (args, allargs);
+
+  flags |= DEBUG_ONLY_THIS_PROCESS;
+
+  if (!inferior_io_terminal)
+    tty = INVALID_HANDLE_VALUE;
+  else
+    {
+      SECURITY_ATTRIBUTES sa;
+      sa.nLength = sizeof(sa);
+      sa.lpSecurityDescriptor = 0;
+      sa.bInheritHandle = TRUE;
+      tty = CreateFileA (inferior_io_terminal, GENERIC_READ | GENERIC_WRITE,
+                        0, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+      if (tty == INVALID_HANDLE_VALUE)
+       warning (_("Warning: Failed to open TTY %s, error %#x."),
+                inferior_io_terminal, (unsigned) GetLastError ());
+      else
+       {
+         si.hStdInput = tty;
+         si.hStdOutput = tty;
+         si.hStdError = tty;
+         si.dwFlags |= STARTF_USESTDHANDLES;
+       }
+    }
+
+  windows_init_thread_list ();
+  ret = CreateProcessA (0,
+                       args,   /* command line */
+                       NULL,   /* Security */
+                       NULL,   /* thread */
+                       TRUE,   /* inherit handles */
+                       flags,  /* start flags */
+                       NULL,   /* environment */
+                       NULL,   /* current directory */
+                       &si,
+                       &pi);
+  if (tty != INVALID_HANDLE_VALUE)
+    CloseHandle (tty);
 #endif
 
   if (!ret)
@@ -1965,18 +2183,18 @@ windows_xfer_memory (CORE_ADDR memaddr, gdb_byte *our, int len,
     {
       DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08lx\n",
                  len, (DWORD) (uintptr_t) memaddr));
-      if (!WriteProcessMemory (current_process_handle, 
+      if (!WriteProcessMemory (current_process_handle,
                               (LPVOID) (uintptr_t) memaddr, our,
                               len, &done))
        done = 0;
-      FlushInstructionCache (current_process_handle, 
+      FlushInstructionCache (current_process_handle,
                             (LPCVOID) (uintptr_t) memaddr, len);
     }
   else
     {
       DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08lx\n",
                  len, (DWORD) (uintptr_t) memaddr));
-      if (!ReadProcessMemory (current_process_handle, 
+      if (!ReadProcessMemory (current_process_handle,
                              (LPCVOID) (uintptr_t) memaddr, our,
                              len, &done))
        done = 0;
@@ -1985,7 +2203,7 @@ windows_xfer_memory (CORE_ADDR memaddr, gdb_byte *our, int len,
 }
 
 static void
-windows_kill_inferior (void)
+windows_kill_inferior (struct target_ops *ops)
 {
   CHECK (TerminateProcess (current_process_handle, 0));
 
@@ -2055,7 +2273,7 @@ windows_xfer_shared_libraries (struct target_ops *ops,
   obstack_grow_str (&obstack, "<library-list>\n");
   for (so = solib_start.next; so; so = so->next)
     windows_xfer_shared_library (so->so_name, (CORE_ADDR) (uintptr_t) so->lm_info->load_addr,
-                                &obstack);
+                                target_gdbarch, &obstack);
   obstack_grow_str0 (&obstack, "</library-list>\n");
 
   buf = obstack_finish (&obstack);
@@ -2099,6 +2317,30 @@ windows_xfer_partial (struct target_ops *ops, enum target_object object,
     }
 }
 
+/* Provide thread local base, i.e. Thread Information Block address.
+   Returns 1 if ptid is found and sets *ADDR to thread_local_base.  */
+
+static int
+windows_get_tib_address (ptid_t ptid, CORE_ADDR *addr)
+{
+  thread_info *th;
+
+  th = thread_rec (ptid_get_tid (ptid), 0);
+  if (th == NULL)
+    return 0;
+
+  if (addr != NULL)
+    *addr = th->thread_local_base;
+
+  return 1;
+}
+
+static ptid_t
+windows_get_ada_task_ptid (long lwp, long thread)
+{
+  return ptid_build (ptid_get_pid (inferior_ptid), 0, lwp);
+}
+
 static void
 init_windows_ops (void)
 {
@@ -2134,14 +2376,26 @@ init_windows_ops (void)
   windows_ops.to_pid_to_str = windows_pid_to_str;
   windows_ops.to_stop = windows_stop;
   windows_ops.to_stratum = process_stratum;
-  windows_ops.to_has_all_memory = 1;
-  windows_ops.to_has_memory = 1;
-  windows_ops.to_has_stack = 1;
-  windows_ops.to_has_registers = 1;
-  windows_ops.to_has_execution = 1;
+  windows_ops.to_has_all_memory = default_child_has_all_memory;
+  windows_ops.to_has_memory = default_child_has_memory;
+  windows_ops.to_has_stack = default_child_has_stack;
+  windows_ops.to_has_registers = default_child_has_registers;
+  windows_ops.to_has_execution = default_child_has_execution;
   windows_ops.to_pid_to_exec_file = windows_pid_to_exec_file;
+  windows_ops.to_get_ada_task_ptid = windows_get_ada_task_ptid;
+  windows_ops.to_get_tib_address = windows_get_tib_address;
+
   i386_use_watchpoints (&windows_ops);
 
+  i386_dr_low.set_control = cygwin_set_dr7;
+  i386_dr_low.set_addr = cygwin_set_dr;
+  i386_dr_low.reset_addr = NULL;
+  i386_dr_low.get_status = cygwin_get_dr6;
+
+  /* i386_dr_low.debug_register_length field is set by
+     calling i386_set_debug_register_length function
+     in processor windows specific native file.  */
+
   windows_ops.to_magic = OPS_MAGIC;
 }
 
@@ -2158,12 +2412,20 @@ _initialize_windows_nat (void)
 
   init_windows_ops ();
 
+#ifdef __CYGWIN__
+  cygwin_internal (CW_SET_DOS_FILE_WARNING, 0);
+#endif
+
   c = add_com ("dll-symbols", class_files, dll_symbol_command,
               _("Load dll library symbols from FILE."));
   set_cmd_completer (c, filename_completer);
 
   add_com_alias ("sharedlibrary", "dll-symbols", class_alias, 1);
 
+  add_com_alias ("add-shared-symbol-files", "dll-symbols", class_alias, 1);
+
+  add_com_alias ("assf", "dll-symbols", class_alias, 1);
+
 #ifdef __CYGWIN__
   add_setshow_boolean_cmd ("shell", class_support, &useshell, _("\
 Set use of shell to start subprocess."), _("\
@@ -2223,9 +2485,7 @@ Show whether to display kernel exceptions in child process."), NULL,
                           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."),
@@ -2239,13 +2499,13 @@ Show whether to display kernel exceptions in child process."), NULL,
 /* Pass the address ADDR to the inferior in the I'th debug register.
    Here we just store the address in dr array, the registers will be
    actually set up when windows_continue is called.  */
-void
+static void
 cygwin_set_dr (int i, CORE_ADDR addr)
 {
   if (i < 0 || i > 3)
     internal_error (__FILE__, __LINE__,
                    _("Invalid register %d in cygwin_set_dr.\n"), i);
-  dr[i] = (unsigned) addr;
+  dr[i] = addr;
   debug_registers_changed = 1;
   debug_registers_used = 1;
 }
@@ -2253,10 +2513,10 @@ cygwin_set_dr (int i, CORE_ADDR addr)
 /* Pass the value VAL to the inferior in the DR7 debug control
    register.  Here we just store the address in D_REGS, the watchpoint
    will be actually set up in windows_wait.  */
-void
-cygwin_set_dr7 (unsigned val)
+static void
+cygwin_set_dr7 (unsigned long val)
 {
-  dr[7] = val;
+  dr[7] = (CORE_ADDR) val;
   debug_registers_changed = 1;
   debug_registers_used = 1;
 }
@@ -2264,10 +2524,10 @@ cygwin_set_dr7 (unsigned val)
 /* Get the value of the DR6 debug status register from the inferior.
    Here we just return the value stored in dr[6]
    by the last call to thread_rec for current_event.dwThreadId id.  */
-unsigned
+static unsigned long
 cygwin_get_dr6 (void)
 {
-  return dr[6];
+  return (unsigned long) dr[6];
 }
 
 /* Determine if the thread referenced by "ptid" is alive
@@ -2314,33 +2574,142 @@ _initialize_check_for_gdb_ini (void)
     }
 }
 
+/* Define dummy functions which always return error for the rare cases where
+   these functions could not be found. */
+static BOOL WINAPI
+bad_DebugActiveProcessStop (DWORD w)
+{
+  return FALSE;
+}
+static BOOL WINAPI
+bad_DebugBreakProcess (HANDLE w)
+{
+  return FALSE;
+}
+static BOOL WINAPI
+bad_DebugSetProcessKillOnExit (BOOL w)
+{
+  return FALSE;
+}
+static BOOL WINAPI
+bad_EnumProcessModules (HANDLE w, HMODULE *x, DWORD y, LPDWORD z)
+{
+  return FALSE;
+}
+
+#ifdef __USEWIDE
+static DWORD WINAPI
+bad_GetModuleFileNameExW (HANDLE w, HMODULE x, LPWSTR y, DWORD z)
+{
+  return 0;
+}
+#else
+static DWORD WINAPI
+bad_GetModuleFileNameExA (HANDLE w, HMODULE x, LPSTR y, DWORD z)
+{
+  return 0;
+}
+#endif
+
+static BOOL WINAPI
+bad_GetModuleInformation (HANDLE w, HMODULE x, LPMODULEINFO y, DWORD z)
+{
+  return FALSE;
+}
+
+static BOOL WINAPI
+bad_OpenProcessToken (HANDLE w, DWORD x, PHANDLE y)
+{
+  return FALSE;
+}
+
+static BOOL WINAPI
+bad_GetCurrentConsoleFont (HANDLE w, BOOL bMaxWindow, CONSOLE_FONT_INFO *f)
+{
+  f->nFont = 0;
+  return 1;
+}
+static COORD WINAPI
+bad_GetConsoleFontSize (HANDLE w, DWORD nFont)
+{
+  COORD size;
+  size.X = 8;
+  size.Y = 12;
+  return size;
+}
+/* Load any functions which may not be available in ancient versions
+   of Windows. */
 void
-_initialize_psapi (void)
+_initialize_loadable (void)
 {
+  HMODULE hm = NULL;
+
+  hm = LoadLibrary ("kernel32.dll");
+  if (hm)
+    {
+      DebugActiveProcessStop = (void *)
+       GetProcAddress (hm, "DebugActiveProcessStop");
+      DebugBreakProcess = (void *)
+       GetProcAddress (hm, "DebugBreakProcess");
+      DebugSetProcessKillOnExit = (void *)
+       GetProcAddress (hm, "DebugSetProcessKillOnExit");
+      GetConsoleFontSize = (void *) 
+       GetProcAddress (hm, "GetConsoleFontSize");
+      GetCurrentConsoleFont = (void *) 
+       GetProcAddress (hm, "GetCurrentConsoleFont");
+    }
+
+  /* Set variables to dummy versions of these processes if the function
+     wasn't found in kernel32.dll. */
+  if (!DebugBreakProcess)
+    DebugBreakProcess = bad_DebugBreakProcess;
+  if (!DebugActiveProcessStop || !DebugSetProcessKillOnExit)
+    {
+      DebugActiveProcessStop = bad_DebugActiveProcessStop;
+      DebugSetProcessKillOnExit = bad_DebugSetProcessKillOnExit;
+    }
+  if (!GetConsoleFontSize)
+    GetConsoleFontSize = bad_GetConsoleFontSize;
+  if (!GetCurrentConsoleFont)
+    GetCurrentConsoleFont = bad_GetCurrentConsoleFont;
+
   /* Load optional functions used for retrieving filename information
      associated with the currently debugged process or its dlls. */
-  if (!psapi_loaded)
+  hm = LoadLibrary ("psapi.dll");
+  if (hm)
     {
-      HMODULE psapi_module_handle;
-
-      psapi_loaded = -1;
+      EnumProcessModules = (void *)
+       GetProcAddress (hm, "EnumProcessModules");
+      GetModuleInformation = (void *)
+       GetProcAddress (hm, "GetModuleInformation");
+      GetModuleFileNameEx = (void *)
+       GetProcAddress (hm, GetModuleFileNameEx_name);
+    }
 
-      psapi_module_handle = LoadLibrary ("psapi.dll");
-      if (psapi_module_handle)
-       {
-         psapi_EnumProcessModules = (void *) GetProcAddress (psapi_module_handle, "EnumProcessModules");
-         psapi_GetModuleInformation = (void *) GetProcAddress (psapi_module_handle, "GetModuleInformation");
-         psapi_GetModuleFileNameExA = (void *) GetProcAddress (psapi_module_handle, "GetModuleFileNameExA");
-
-         if (psapi_EnumProcessModules != NULL
-             && psapi_GetModuleInformation != NULL
-             && psapi_GetModuleFileNameExA != NULL)
-           psapi_loaded = 1;
-       }
+  if (!EnumProcessModules || !GetModuleInformation || !GetModuleFileNameEx)
+    {
+      /* Set variables to dummy versions of these processes if the function
+        wasn't found in psapi.dll. */
+      EnumProcessModules = bad_EnumProcessModules;
+      GetModuleInformation = bad_GetModuleInformation;
+      GetModuleFileNameEx = bad_GetModuleFileNameEx;
+      /* This will probably fail on Windows 9x/Me.  Let the user know that we're
+        missing some functionality. */
+      warning(_("cannot automatically find executable file or library to read symbols.\nUse \"file\" or \"dll\" command to load executable/libraries directly."));
     }
 
-  /* This will probably fail on Windows 9x/Me.  Let the user know that we're
-     missing some functionality. */
-  if (psapi_loaded < 0)
-    warning(_("cannot automatically find executable file or library to read symbols.  Use \"file\" or \"dll\" command to load executable/libraries directly."));
+  hm = LoadLibrary ("advapi32.dll");
+  if (hm)
+    {
+      OpenProcessToken = (void *) GetProcAddress (hm, "OpenProcessToken");
+      LookupPrivilegeValueA = (void *)
+       GetProcAddress (hm, "LookupPrivilegeValueA");
+      AdjustTokenPrivileges = (void *)
+       GetProcAddress (hm, "AdjustTokenPrivileges");
+      /* Only need to set one of these since if OpenProcessToken fails nothing
+        else is needed. */
+      if (!OpenProcessToken || !LookupPrivilegeValueA || !AdjustTokenPrivileges)
+       OpenProcessToken = bad_OpenProcessToken;
+    }
 }
This page took 0.041041 seconds and 4 git commands to generate.